今年承担了一个额外工作是参加公司每个季度的生产事故复盘,并总结经验,然后在整个公司进行宣贯。今年总共复盘了近70起生产事故案例,说实话,看着很痛心,因为99%的错误都不是什么高大上的问题,都是一些低级错误。70%都是数据库sql的问题。大家都说不想做CURD码农,可就是CURD有些人也没玩明白,或者说忽略了CURD的重要性,SQL真的是非常重要,你轻视它,那么它就一定会反噬你。11月份发生了一起极其严重的事故,损失金额达到billion级别,事故原因就是一个update语句的问题。我们是金融业,一个小疏忽可能就是超大事故,相关人员要么被开除,要么就被取消绩效评优资格,很惨。
所以,无论作为开发者,还是管理者,切不可好高骛远,眼高手低,只有脚踏实地才能够仰望星空。不要总是高谈阔论,上来动不动就谈高并发,谈分布式。大道至简是万物的理想状态。
先分类讨论下我复盘过的生产事故案例,下面我所有列举的例子都是切切实实地在我们公司发生的案例。所以我很希望所有开发者,无论是有经验的专家,还是初入职场的新人,都能从中吸取教训,有则改之无则加勉。我写到这儿的时候,虽然立刻就想起了当年明月在《明朝那些事儿》的结尾写的那句话:“人吸取到的最大教训就是从来不吸取历史的经验教训,还是会原原本本地将前任犯过的错误再犯一遍。“。可是,聊胜于无,我还是相信写出来是有用处的。
一、SQL问题
1、集团外系统间定时转账 - 复合条件没有指定优先级
现象:定时任务触发转账退款,发生相同转账重复执行,导致重复退款;
影响:多转给其他公司账款,金额达到billion,已经惊动我们最高层。好在钱都已经追回来;
原因:有位同事写的update语句有多个判断条件,由于保密性问题,这里脱敏,如where语句
where a and (b is null or b == "" or b =="0"),这是它本应该使用的where语句,可是它的where语句却没有了括号,即where a and b is null or b == "" or b =="0"。看到这里,大家都知道问题出在哪里了吧。
分析:这位同事是用mybatis API写的,一是对API的使用不熟悉,二是单元测试没有写好,三是功能测试也不充分,总之每个关系都没有引起足够的重视。
2、某核心系统突发宕机 - 分库分表场景没有where,没有分片键
现象:高峰时段交易成功率降级,系统宕机;
影响:所有关联的外围系统受到影响,引起大量客诉;
原因:一位同事在写数据库查询语句时,没有加任何非空判断,再加上因为某种原因,前端传过来的数据所有where条件都是空,在分库分表的场景下,进行了一次牛逼的聚合查询,也就是把每个子库的数据都查出来,进行聚合。直接导致系统出现OOM,当多次的GC依然满足不了的情况下,内存占用依然很大,Linux操作系统本身也会检测内存占用情况,如果发现某个进程内存占用过多,就会kill掉的。
分析:我们在写where查询时一定要非常注意where的条件的非空判断,否则很容易出现慢sql的问题,在高并发场景下,慢sql影响的不仅仅是数据库本身,也影响应用,影响整个系统。尤其是分库分表,分库分表场景下,在线交易千万不要做聚合查询,一定要带上分片键。如果想做聚合查询,请采用其他的手段。可以将所有数据归档到一个聚合库,聚合库可以

1677

被折叠的 条评论
为什么被折叠?



