凌晨三点,手机在枕头底下震得像个陀螺。我眯着眼摸到手机,屏幕上跳出十七个未接来电和一条消息:“数据库挂了,前台全部瘫痪。”那一刻的清醒程度,比任何咖啡都管用。干这行十年,数据库故障从来不会挑工作时间来,它们专挑你睡得最沉、值班人最少的时候出手。但每次从这样的夜晚爬起来,我都能在半小时内让业务恢复,靠的不是运气,而是一套刻在肌肉里的故障处理流程。

数据库故障的第一原则,不是“修好它”,而是“先让它跑起来”。很多新手一上来就扎进错误日志里找根因,翻了两小时还在翻,前台业务已经凉透了。正确的做法是,先判断故障级别:如果只是某个查询变慢,那就先杀掉阻塞会话,给业务喘口气;如果是整个实例宕了,第一时间尝试重启,重启能解决八成以上的临时性故障。记住,你的KPI是恢复业务运行,不是当福尔摩斯。业务恢复了,哪怕根因没找到,你也有充足的时间去排查,而不是被业务方拿刀架在脖子上催。
说到重启,这里有个血泪教训。有次我遇到MySQL实例无响应,二话不说执行了service mysql restart,结果等了十分钟还没起来。一看日志,InnoDB在做崩溃恢复,而那个表有二十亿行数据。所以重启之前,一定要先看一眼错误日志,判断是不是需要长时间恢复的场景。如果你发现是磁盘满、文件损坏或者主从延迟导致的故障,那就别盲目重启了,先解决前置条件。另外,重启前一定要记得备份配置文件和数据目录,哪怕只是cp一份到/tmp,都能让你在误操作后不至于下跪。
故障处理里最坑人的,是“假故障”。有次业务方报数据库连接超时,我ping了一下IP,通了,端口也通,MySQL进程也在,看起来一切正常。但业务就是连不上。后来发现是连接数被占满了,全是sleep状态的空闲连接,把连接池堵得死死的。这种问题,你重启数据库当然能解决,但治标不治本。正确的做法是,先查show processlist,把那些长时间sleep的会话干掉,再调低wait_timeout,让开发检查连接池配置。数据库故障,十有七八不是数据库本身的问题,而是上游的连接管理、应用逻辑或者网络配置出了问题。
说到网络,我遇到过一个特别诡异的案例。数据库一切正常,CPU、内存、IO全部健康,但业务反馈查询偶尔超时。排查了两天,发现是交换机端口上有个微小的光模块故障,导致数据包间歇性丢失。这种间歇性问题最折磨人,因为它不持续,你抓包的时候它偏偏正常。遇到这种情况,别只盯着数据库监控,要把网络链路、DNS解析、负载均衡全都过一遍。有时候数据库故障的根因,根本不在数据库这一层,就像你感冒了咳嗽,病因可能在肺,也可能在咽喉。
处理故障时,最忌讳的就是“一个人扛”。很多DBA有英雄情结,觉得出了事自己默默搞定最有成就感。但现实是,你一个人埋头修的时候,业务方在等,领导在问,开发在猜,整个团队都在焦虑。正确的做法是,先发一条简短的状态通报,告诉所有人“故障已确认,正在处理,预计恢复时间X分钟”。然后每五分钟同步一次进展。这样做的好处是,即使你一时半会儿修不好,大家也清楚发生了什么,不会产生恐慌和谣言。等故障解除后,再发一条完整的复盘报告,包括根因、影响范围、修复措施和后续预防方案。
说到复盘,这才是故障处理里最有价值的部分。但很多人把复盘写成了检讨书,通篇都是“责任心不够”“测试不充分”这种正确的废话。真正的复盘,要回答三个问题:为什么会发生?为什么当时没发现?以后怎么防止?比如上次主从切换导致数据丢失,根因是半同步复制配置成了异步,当时没发现是因为监控只看了主库的延迟,没看从库的落库情况。以后怎么防止?把半同步复制打开,加上从库数据校验的定时任务。只有这样的复盘,才能让你在下次故障来袭时,多一层防护。
数据库故障处理,说到底拼的不是技术深度,而是决策速度和冷静程度。技术再牛的人,遇到故障慌了神,照样把简单问题搞复杂。我见过太多人,在故障现场手忙脚乱,一会儿查这个一会儿查那个,连自己改过什么配置都记不清了。所以,每次处理完故障,我都会把操作步骤记到自己的笔记里,包括当时是怎么判断的、为什么选这个方案、有没有更好的办法。日积月累,这些东西就成了你的故障处理手册。下次再遇到类似问题,你甚至不用动脑子,肌肉记忆就能帮你做出正确决策。
回到凌晨三点那个电话,我后来用了二十二分钟恢复了业务。流程很简单:先确认是主库磁盘满导致写入失败,然后清理了binlog日志腾出空间,接着重启了数据库服务,确认主从同步正常。整个过程没有用到什么高深的技术,就是按部就班地执行预案。但如果你没有预案,没有平时的演练,没有对故障处理流程的肌肉记忆,那这二十二分钟可能就变成二十二个小时。数据库故障不可避免,但快速恢复业务运行,靠的是日复一日的准备和练习。每一次故障,都是你升级打怪的机会,处理得越熟练,下次就越从容。


