前言:
线上数据如果出现问题,必须是优先处理,其优先级 > 待上线项目 > 测试bug > 开发中项目。所以假如出现线上问题,需要马上处理。
线上问题场景1:假设有一个脚本跑用户转发介绍赠送礼品的数据,但是由于发版问题导致数据不一致,并且在几天后有用户投诉发现了这个问题。发现的情况是由于表库部分没建立,到时部分数据重复插入,用户不断获得礼品。
针对这种线上问题,无非是人为疏忽导致的,预防的方案如下:
- 1 执行的Job没有加事务,不具备原子性,导致数据部分插入
- 2 未有预发版环境,发版SQL没准备好,导致更新SQL缺少
- 3 上线后未做回归测试
当然这里不是教你怎么预防,是教你怎么处理这个不一致的数据,处理方案如下:
- 1 由于涉及到了不少用户利益,所以我们采用了跑脚本跑出多条update语句的方式来修复数据
- 2 首先编写脚本,查出所有出问题时间赠送的日志,然后查出来对应用户赠送数量,并且拼接为多条UPDATE SQL,大致如下:
-------------------------------------------------------------------------------------------------
UPDATE `xxxx`.`userproductinfo` SET GiftCourseNumber=GiftCourseNumber - 18 WHERE userId=252035;
......................................
UPDATE `xxxx`.`userproductinfo` SET GiftCourseNumber=GiftCourseNumber - 20 WHERE userId=213505;
- 3
-------------------------------------------------------------------------------------------------
- 3 测试到生产数据库校验待更新数据正确性,确认正确后执行所有UPDATE SQL
- 4 确认更新完之后,根据时间重新跑脚本(脚本必须要有可重复性,可多次重复跑),跑出正确的数据
总结:为什么不直接写sql?一个sql批量update不好吗?原因是这里涉及的数据比较重要,改错了很麻烦,所以就跑脚本,并且把待更新的sql统一输出来进行审查。
线上问题场景2:假设线上有部分历史数据的创建时间create_time为空,导致了某个功能引用这个数据的时候报NPE异常。
针对这个线上问题,无非是历史数据导致的,并且这个问题并不面向用户,不涉及金额,创建时间createTime也不是一个重要的字段,所以可用sql直接更新修复。
处理方案如下:
1 编写批量更新sql如下:
--------------------------------------
UPDATE `xxx`.teacherinfo a1
INNER JOIN `xxx`.account_info a2
INNER JOIN `xxx`.account a3
INNER JOIN `xxx`.account_teacher_relation a4
SET a1.CreateTime = a2.gmt_create
WHERE a2.id = a3.id
AND a.username = atr.account
AND a3.teacher_id = a1.id
AND a1.createTime IS NULL;
--------------------------------------
2 执行完当前sql后,发现部分数据无对应创建时间可迁移,这时候可以给一个默认的创建时间即可,如下:
UPDATE teacherinfo set createTime='2019-05-01 00:00:00' WHERE createTime IS NULL;
总结:上面数据的createtime导致了NPE,并且这个字段是不重要的,我们可以直接用sql处理,将其它表的创建时间迁移到这张表上。另外给那些无对应数据的记录一个默认的创建时间即可(因为原来部分数据就是导入的,给的就是默认创建时间)。