得知下厨房的数据被误删了,正在紧张恢复中。作为犯过很多次严重错误的人,我最想说的是,善待当事人吧,此刻他在承受着巨大的压力,比其他任何人都要心焦,他会很感激你的善言和善意。
这几年犯过很多次严重影响线上服务的错误,像重启了错误的节点这样的事情应该算作能够对线上造成影响的最微不足道的错误,就只简单说几件现在都还让我心有余悸的事吧。
停用线上 memcache 集群
在调整 memcache 客户端配置的使用和部署方式之前,尽管经过了多次测试,比如在部分节点先上线,确认没有问题之后上线所有的应用服务器,但还是使用了错误的配置,导致线上所有应用禁用了 memcache,巨大的访问压力瞬间拖垮了数据库,从发现问题到完全恢复持续了将近二十分钟。
软件 bug 导致线上 memcache 集群被污染
上线的代码在特定条件下会禁掉对 memcache 的使用,导致在本应清除 cache 的情况下没有清除,污染了整个线上的 memcache 集群,后果是各处功能出现诡异的问题,比如提醒死也叉不掉… 不得不将整个 memcache 集群 flush 一遍消除影响,耗时半天。
恢复数据时删除了更多数据
线上有豆列被误删了,从备份紧急恢复时,使用 mysqldump 导出需要恢复的那部分数据,但是遗憾的是连 DROP TABLE ... 也一起 dump 了,并且在线上执行之前都没有意识到。结果,原本需要恢复的只是一个豆列,恢复之后只剩下了一个豆列,豆列功能紧急只读,重新恢复数据并做数据合并…
数据库主从切换时从库还未跟上同步
我在给从库热身,准备切换主从,这时候有两个不愿意透露姓名的同事来找我聊另外一件事情,很愉快地聊完,我愉快地发现已经热身完了,于是愉快地用土脚本做了主从切换,然后悲剧地收到了报警,数据冲突同步中断了,原来是热身过程中从库因为压力比较高造成的滞后还未追平,而我已经愉快地做了切换。
误操作并误删数据文件
在一次主从切换之后,我突然发现新的 slave 同步在继续,但是 binlog 却停止写入了,之后惊讶地发现 master 上的 SQL_LOG_BIN 竟然是一个 global 级别的变量,并且值是 0。原来是之前在 slave 上调整索引时,本该 SET SQL_LOG_BIN=0,却无意识地执行了 SET GLOBAL SQL_LOG_BIN=0,禁用了整个 slave 实例而不只是当前 session 的 binlog,主从切换之后,整个集群就只剩下了一个节点有完整的数据,在我发现并修复这个问题之前,新 slave 上已经缺失了 3 分钟的数据。尝试了各种方法,想要准确无误地修复这 3 分钟的数据还是挺有难度的,尤其是在承受巨大精神压力的情况下,只好选择了从 master 重建。然而在我备份完 master 节点,重建新 slave 时又误删了 slave 上的数据文件,这下更刺激了,在新的 slave 重建完成之前,如果 master 宕机,我就真的连一个可以应付线上压力的节点都没有了,哪怕是一个缺少了 3 分钟数据的实例。
在发生这些事情时,真的是想死的心都有,支撑我的还有一个信念:无论如何把这个烂摊子收拾完了再死!而有过这样的经历,我就非常感激那些本来有绝对权利责难我,但在事情发生时立刻马上挽起袖子和我一起解决问题,事后帮我一起想办法如何避免这样的问题再发生的人,比如不愿意透露姓名的 hongqn 和 flycondor。
经历和看到过越多这样的事情,我就越觉得犯错是不可避免的,无论你思维有多缜密,行事有多谨慎,只要做事就无可避免地会犯错误,或大或小,甚至现在每隔一段时间发现自己没有在线上犯错误,就会想:我最近在干嘛?
最后,备份不做,日子甭过,真的会有半夜鬼敲门,另外,作为 SA 或 DBA,真的需要确保每一个危险操作都至少是可以 rollback 到上一步的,并且在进行下一步操作之前,要确认所有已知状态都是正常的,工具比人更擅长做这些事,人的精力应该花在让这些工具更加可靠上。
注:最后一个问题涉及 MySQL 5.5 相对于之前版本的一个行为变化,参考:
原文链接:http://blog.xupeng.me/2013/06/27/mistakes-in-production-system-these-years/