直接操作数据库能否作为解决问题的常规手段

前段时间在网上看到一个讨论,就是目前很多业务和产研同学会习惯直接通过修改数据的方式来解决一些问题,比如修改订单状态、修改用户状态等。提出问题的同学觉得这不合适,他提出的理由是:

  1. 本来是临时方案,现在却成了常规手段,团队会习惯这种思考和做事的方式
  2. 不经过正常的功能修改数据,可能会导致数据不一致,引起业务上的问题
  3. 没有经过测试的数据变更,小则引起bug,大可能导致数据丢失等灾难性后果
Photo by Rubaitul Azad

很多数据变更的操作都有时效性要求,比如功能不完善引起的数据错误需要及时修正,这时候客户不可能等你完善产品功能。还有些数据变更,比如修改某个字段的默认值,就是临时性的操作,也不可能开发相应的功能来支持。提出问题的同学也承认,当出现这些情况时,直接修改数据库确实是最方便、最有效的手段。那么我们是否应该把它作为常规手段呢?还有更妥善的解决方案吗?如果有其他方案,有什么好的流程/方式能避免大家通过更改数据库解决问题的?

研发的同学应该都理解,很多情况下,维护业务数据或是做数据修复,直接操作数据库是不可避免的。换句话说,直接修改数据库就是很多同学的日常工作,就是常规手段。那么问题就是不是能不能避免,而是如何规避或是降低其带来的风险?

回答问题的人也挺专业的,给了两个不错的建议。

如果需要操作数据(DML),尤其是操作大量的数据,建议通过脚本工具来操作。从技术上来讲,如果我们操作的数据量比较大,譬如 UPDATE A SET field=x WHERE condition < y ,如果条件没有合理的索引,甚至是没有索引,可能会导致锁表,进而影响线上业务。如果是通过脚本来操作,可以按照一定的规则分批处理,并同日志来记录修改了哪些数据、操作前后的变化等,留待后面追溯。另外脚本也是程序,可以放到GIT仓库做版本控制,也方便做CodeReview。尤其是要操作大量数据的程序,需要更多的人一起CodeReview,避免逻辑错漏,造成业务故障。

如果是对数据库表结构的变更(DDL), 可以通过一些 DMS(Data Management Service) 工具来解决。如果数据库使用的是云产品,一般都提供对应DMS工具,这些工具天然集成了针对DML以及DDL相关操作的审核机制,想要对线上数据库做变更,需要提交一个DML或者DDL的申请,DMS工具会先对SQL做前置检查,例如语法是否合规,是否有应用到索引,如果是Alter语句,是否有锁表的风险等等。前置检查过了,至少需要另一个人再做一次审核,审核通过后,申请人才能完成执行。通过这一整条链路,降低线上数据误操作的风险。如果没有使用云产品,也有开源的DMS解决方案,可以了解使用。

其实,维护线上数据也是我的日常工作,而且上面的部分建议对我来说都没用。因为我的团队就我一个人,没人来CodeReview,更麻烦的是MongoDB的DMS工具实在不咋的,只能说聊胜于无。对我来说,避免手抖,降低事故的概率仅能靠我自己来保证。

所以我给自己制定了几条需要严格遵守的规则:

  1. 所有的数据变更操作都需要在线下测试环境中测试,未经操作,绝不允许到生产环境执行
  2. 如果需要修改多条数据,我一定会先跟业务的同学确认到底要修改多少条数据,把修改语句中的查询条件单独拿出来去查一下,看看数量与业务同学期望是否一致,如果不一致则需要修改
  3. 如果是修改少量数据,我会先把这两条数据内容查询出来,放到记事本里备份(MongoDB的一条数据即一个json对象)
  4. 如果是修改大量数据,我会先把整个表备份一下(得亏是做企业业务,每张表的数据没有想象那么多,备份也很快)
  5. 上述操作都通过后,再到生产环境执行对应的更新操作,删除操作也是同样的流程
  6. 对于比较复杂的更新操作,我还是会通过代码来实现,代码经过测试后发到生产,手动调用接口

经过这些步骤后,到目前为止还没发生过事故。当然,我希望云平台能够早日优化下MongoDB的DMS工具,也更希望不久以后能有同学一起来做CodeReview。