史荣久

史荣久的博客

他的个人主页  他的博客

SQL不慎迷失在WHERE

史荣久  2009年11月23日 星期一 08:38 | 1166次浏览 | 0条评论

SQL不慎迷失在WHERE
作者:臭豆腐[trydofor.com]
日期:2009-11-21
授权:署名-非商业-保持一致 1.0 协议
声明:拷贝、分发、呈现和表演本作品,请保留以上全部信息。

文档目录
1. 灾难回顾
出于各种业务需要,项目经常使用SQL手工维护数据。
5个年头里,大概有过4次刻骨铭心的WHERE灾难。

所谓灾难,一般具有以下一些特征。
  • 影响了正式生产环境。
  • 破坏了百万级或千万级的记录。
  • 数据关系复杂,极难还原。
  • 几人日的工作或通宵才能恢复。

造成灾难的原因都十分低级,十分低概率,不经历过也许不会相信,
也许再仔细那么一点点,也许再慢那么一小会儿,就完全可以避免。
但事实是,人是会在某些时候短路,犯不可能的低级错误的。

2. 防范措施
正确完成一个操作,我们需要把正确的SQL执行在正确的数据库上。
取其反,结果可能就是一个灾难。

两类错误,
  • 错误的服务器
  • 错误的但可执行的SQL

三种情况,
  • 正确的SQL执行在错误的数据库上。
  • 错误但可执行的SQL执行在正确的数据库上。
  • 错误但可执行的SQL执行在错误的数据库上。

防范上最为有效的措施是,结对操作,即找个搭档当听众,
把操作上的每一步逻辑和目标讲给他听,并得其确认。

2.1. 正确的数据库
要求上,必须在连接前和链接后确认。操作上,有以下几种策略,

  • 关闭所有无关的链接,或关闭客户端程序。
  • 确认目标数据库的连接,并起个醒目而直接的名字。
  • 连接后,找服务器特征数据,查看确认。

2.2. 正确的SQL
危险的SQL是UPDATE和DELETE,错误但可执行的SQL一般为,
  • 单条SQL,WHERE残缺或错误。
  • 一组SQL,丢失部分SQL。
  • 一组SQL,混入其他SQL。

一组SQL的情况,防范起来比较容易,做好确认和清场工作就可以了。
单条SQL的情况,最为常见和且危险最大。通常做一些制度防范。

第一,全部数据UPDATE和DELETE时,强制使用WHERE 1=1。
< sql > 强制WHERE 
            001
002
003
004
005
006
007
008
009
010
011
012
           
            
             // 正常 UPDATE
            
            
             UPDATE
            
            TEST
            
             SET
            
            FIELD1=
            
             1
            
            ,FIELD2=
            
             2
            
            
             GO
            
            
             // 强制WHERE UPDATE
            
            
             UPDATE
            
            TEST
            
             SET
            
            FIELD1=
            
             1
            
            ,FIELD2=
            
             2
            
            
             WHERE
            
            
             1
            
            =
            
             1
            
            
             GO
            
            
             // 正常 DELETE
            
            
             DELETE
            
            
             FROM
            
            TEST
            
             GO
            
            
             // 强制WHERE DELETE
            
            
             DELETE
            
            
             FROM
            
            TEST
            
             WHERE
            
            
             1
            
            =
            
             1
            
            
             GO
            
           

第二,部分数据UPDATE和DELETE时,更新前必须SELECT。
即,把SELECT的WHERE完整的使用在UPDATE和DELETE上。

< sql > 强制SELECT 
            001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
           
            
             // 正常 UPDATE
            
            
             UPDATE
            
            TEST
            
             SET
            
            FIELD1=
            
             1
            
            ,FIELD2=
            
             2
            
            
             WHERE
            
            FIELD3 =
            
             3
            
            
             GO
            
            
             // 强制SELECT UPDATE
            
            
             SELECT
            
            FIELD1=
            
             1
            
            ,FIELD2=
            
             2
            
            
             FROM
            
            TEST
            
             //UPDATE TEST SET FIELD1=1,FIELD2=2
            
            
             WHERE
            
            FIELD3 =
            
             3
            
            
             GO
            
            
             // 正常 DELETE
            
            
             DELETE
            
            
             FROM
            
            TEST
            
             WHERE
            
            FIELD3 =
            
             3
            
            
             GO
            
            
             // 强制SELECT DELETE
            
            
             SELECT
            
            FIELD1=
            
             1
            
            ,FIELD2=
            
             2
            
            
             //DELETE
            
            
             FROM
            
            TEST
            
             WHERE
            
            FIELD3 =
            
             3
            
            
             GO
            
           

说明,强制SELECT主要是为了观察数据,COUNT(1)或关键字段经常用到。
执行的时候分两次,第一次单条全选,第二次从注释开始选。

3. 补救套路
在既有的容灾策略上,减少或消除不良影响,基本套路有,

  • 基于备份回到过去。
  • 根据履历从头再来。
  • 回到过去并从头再来。

操作上,
首先,要冷静,权当在做梦,虚惊一场。
一般发生这事,相关人员会出汗,发热,而发热的头脑只能导致更发热的事故。

然后,回顾细节和确定影响,及时沟通和上报。
三个臭皮匠顶个诸葛亮,纯客观的一五一十的把事情说清楚,以便决策。

最后,确定补救策略和实施细节。
考虑到各种情况和对策,并在实施前,逐条重述一边。

关键一点,整个过程全部精力锁定在如何补救上,不得追究责任或评估后果。

评论

我的评论:

发表评论

请 登录 后发表评论。还没有在Zeuux哲思注册吗?现在 注册 !

暂时没有评论

Zeuux © 2024

京ICP备05028076号