员工写了个比删库更可怕的Bug!( 二 )


.values()
.stream()
.map(indices -> indices.stream()
.map(userBakList::get) // 根据索引获取 User 对象
.collect(Collectors.toList())) // 每组1000个元素的列表
.collect(Collectors.toList()); // 所有分组的列表
List<CompletableFuture<Void>> completableFutureList = new ArrayList<>();
int i = 1;
for (List<UserBak> groupedBakUser : groupedBakUsers) {
int finalI = i;
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
boolean b = userBakService.saveOrUpdateBatch(groupedBakUser, batchSize);
});
i++;
completableFutureList.add(completableFuture);
}
CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[]{})).join();
}
使用这种方式,很快数据就恢复完成了 。
当然,还有更简单的方式,比如联表查询、对比哪些数据行发生了变动,再去做修改 。只不过当时情况紧急、再加上数据库量级可控,我们选择了相对理解成本最低的方式 。
之后 , 我这边又手动做了一次全量备份 , 并且思考了一下还有没有遗漏的问题 , 才恢复上线 。
三、事后复盘
整个事故时长接近 2 个小时,大致分为:

  • 人工发现事故(30 分钟后通过用户反馈才得知)
  • 定位问题(5 - 10 分钟)
  • 策略制定和同步(5 - 10 分钟)
  • 数据备份恢复(15 分钟)
  • 增量数据同步(40 分钟)
  • 上线前备份(10 分钟),同时进行其他考虑
从某种意义上来说,这次的事故比直接删库更严重!因为删库了赶紧恢复就好,但这次不仅出现了 “数据污染”,还出现了 “越权” 的问题 , 我们网站内仅管理员可见的敏感信息会存在泄露风险 。好在我们也没什么敏感信息哈哈 。
还有就是用户可能会利用漏洞来薅鱼毛(管理员可以大量获?。??但经过我们的统计 , 这段时间利用漏洞薅鱼毛的人数寥寥无几,大家都是非常善良的,这才放下心来 。
虽然这次的事故带来的损失不是特别大,但也发现了我们系统存在的问题 。
我也跟这位员工说:出了事情不可怕,可怕的是不知道改正,出现同样的事情 。
那么应该如何防止出现类似的事故呢?
1、控制操作权限
为了防止用户执行 update、delete 操作时不小心漏掉了 where 条件、直接更新全量数据 , 企业中一般是会禁止不带 where 条件的修改操作的 。
出现这次的事故后,我也立刻给 MySQL 开启了 sql_safe_updates 配置:
员工写了个比删库更可怕的Bug!

文章插图
缺少 where 条件的更新会直接触发下列报错:
员工写了个比删库更可怕的Bug!

文章插图
之前为什么没加?主要是因为以前都是自己一个人开发系统 , 而且会有需要全量更新的场景,图省事儿 。
2、生产环境隔离
正常情况下,不应该允许直接在本地连接和操作线上数据库的数据 。而是需要先编写代码、提交代码审核、发布上线后,再执行修改操作 。
像这次的事故,如果员工不是本地直接更新数据库,而是提交代码给我看一下 , 我大概率就会发现他少写了更新条件,就能防止了 。
其实之前在腾讯的时候,我都会严格注意这些事项的 。但之所以现在自己公司的项目是允许员工在本地连接线上的,想必大家也能猜到原因 —— 业务规模小、人数少,直接在同一个库开发会方便一些 。
但如果项目的规模上来了,一定要做好多套环境的隔离,本地环境、测试环境、预发布环境、线上环境都要严格区分了 。
3、SQL 审批
之前在腾讯的时候,想要修改关键库的数据,不能直接执行 SQL 语句,而是要先把 SQL 语句提交到审核平台,等你的领导和数据库运维确认没问题后,才能执行 。这样每条 SQL 都是至少有 2 个人看过的,能够大大增加安全性 。
曾经我觉得这种机制很麻烦,但经历过一些血泪教训后 , 才意识到这个环节真的是泰裤辣!
4、数据库审计
数据库审计是指记录和监控数据库的访问及 SQL 语句执行情况,从而精细化风险控制,提高数据安全性 。
可以自己在数据库配置(比如开启日志、使用审计插件等) , 也可以使用第三方云服务自带的审计规则配置 。
5、提升风险意识
最不需要技术,却也是最重要的一点,那就是要让团队的所有同学意识到这件事情带来的风险、问题的严重性 。


推荐阅读