一个外键引起的意外

清明假期刚结束,就被客户火急火燎地叫到了现场-食堂业务系统出现了问题,员工无法刷卡吃饭。

和我一起到场的还有开发工程师,简短的了解过后,直接说出了“EMPLOYEE_INFO和CARD_INFO全部清空,重新同步一遍”这样的豪言壮语,我先是一惊,然后微微反驳了一下但还是遵从了开发工程师的指示,毕竟在内部逻辑还不明朗的情况下,整个清空一张表的行为还是很危险的,在后面也印证了我的担心。

简单说明下问题:客户在4月3日晚发现有张员工卡的信息出现了错误,遂自行对数据库的表进行了更改,认为这只是一个小问题自己完全有能力解决。结果导致整个食堂业务系统奔溃,绝大部分员工员工无法正常刷卡用餐,消费记录丢失。

刚到现场,开发工程师当然是以先恢复业务为优先,毕竟临近中午,还能测试下。在备份了两张表后,清空了EMPLOYEE_INFO和CARD_INFO表,然后全同步了一遍,测试发现,逻辑错误,清空后用户与卡的关系变成了多对多,所有卡刷卡失败,报表读取不能,应用管理不能,系统可以说是废了。

那只有数据库回滚这一条路了。客户说,是4月3日晚出的问题,那就回滚到4月2日吧。回滚完成,再次全同步,还是失败,而且发现消费记录竟然缺失大半,慌了。不断回滚,直到3月24日的备份才正常,中间还发现,新上的备份软件没经过测试,所有的增量备份皆不可用,直接丢失了14天的数据。

几个人埋头寻找原因,最终发现是一个外键引起的意外。

消费记录表中,员工编号是外键,对应的是员工表中的编号。如果把员工表全部删除,由于有外键约束,为了维持数据的一致性,直接导致消费记录表中所有记录也被清零了。

原因找到了,客户一脸懵逼的说,4月3日确实全删除了一遍员工表。。。在客户的强烈要求下,尝试恢复3月24日至4月3日的消费记录,作为一个半吊子SQLSERVER工程师,对SQLSERVER语法甚是生疏,导致恢复语句写了3个小时,才将16318条数据完全匹配删。

最主要的一条SQL分享下:

SELECT DISTINCT D.ID

,D.EmpID

,D.par_id

,D.CardNum

,CONVERT(CHAR(23),D.RecordDate,21) RecordDate

,D.times

,D.amount

,D.MachineNum

,D.Balance

,D.CAR_NO

,D.WORKER_NO

,C.EMPLOYEE_NO

,C.ID_CARD

,C.ID_EMP

FROM [CardThrough].[dbo].[CT_Catering_Change] D

LEFT JOIN (SELECT A.ID ID_EMP

,A.WORKER_NO

,B.ID ID_CARD

,B.EMPLOYEE_NO

,B.FRONT_NO,A.CAR_NO

FROM [CardThrough].[dbo].[EMPLOYEE_INFO] A FULL

JOIN [CardThrough].[dbo].[CARD_INFO] B

ON (A.ID = B.EMPLOYEE_NO AND A.CAR_NO = B.FRONT_NO AND A.ID = B.EMPLOYEE_NO)

WHERE B.DELFLAG = 0) C

ON (D.CardNum = C.CAR_NO

AND D.WORKER_NO = C.WORKER_NO)

这几张表逻辑本身就比较混乱,字段冗余,而且由于客户还对内容进行了少许修改,所以梳理起来就更难了。

虽然用了不少时间,但是学到了不少,一个小小的外键就能引起如此大的问题,以至于开发工程师直接让我把外键约束给删了,防止意外的再次发生。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180409G1YHG700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券