一个备份锁表怎么让CPU飙到100%?完整故障链复盘+避坑清单

📅 2026/6/17 11:53:28
一个备份锁表怎么让CPU飙到100%?完整故障链复盘+避坑清单
今日关键词CPU 100%、从库备份、锁表、Full GC、级联故障、线程池、故障复盘、DBA大家好我是数据库小学妹 凌晨3点手机震醒的时候我整个人是懵的。CPU 100%告警。我之前猜过慢SQL、连接风暴、甚至以为是攻击。直到亲身经历了一次。根因居然是从库的一个备份任务。今天完整复盘一下。故障时间线凌晨3点15分。收到CPU 100%告警。打开监控一看Java应用CPU打满了。JVM堆内存Old区也快顶到头。Full GC每几秒就触发一次。我当时第一反应是是不是有慢SQL连上去看了眼数据库SHOWPROCESSLIST;结果吓了一跳。大量查询的状态全是Waiting for table lock。连接池被占满了。再查锁的情况SHOWENGINEINNODBSTATUS;看到了一个熟悉的关键词FLUSH TABLES WITH READ LOCK。从库正在跑物理备份。这个命令会锁全库。所有读查询全被挡住了一个接一个排队。根因从库备份锁表问题出在备份策略。从库物理备份时执行了这个命令FLUSHTABLESWITHREADLOCK;备份工具靠它来拿到数据文件的一致性快照。但代价是锁释放之前所有查询全部阻塞。主库正常写入从库应用日志也正常。但应用侧的从库读请求全部超时堆积了。完整故障链这个故障是典型的级联故障。我后来画了张图才彻底搞明白。一切从备份锁表开始。FLUSH TABLES WITH READ LOCK拿到全局读锁后所有从库读查询被阻塞。查询进来了但跑不了就在连接池里排队等着。问题来了。每个排队的查询对应的JDBC连接和ResultSet对象都还占着内存。查询越来越多线程池里的活跃连接一路飙升。堆内存迅速上涨Old区很快被打满。到这一步其实还有救。但JVM发现Old区满了开始疯狂触发Full GC。问题是这些被阻塞的线程对象根本回收不掉——它们还在活着在等锁。GC跑了一遍又一遍什么都回收不了。我后来用jstat确认了这一点jstat-gcutilpid1000Full GC次数在飞涨每次回收后Old区占用几乎没降。当时那堆数字我看不太懂后来才知道这叫GC风暴——GC线程和业务线程抢CPU但业务线程都在等锁CPU基本全被GC吃掉了。最终结果Java应用线程池耗尽CPU 100%服务完全不可用。从一个备份锁表到整个服务崩掉一环扣一环每一步都不致命但叠加起来就要命。快速止血找到从库正在执行备份后手都在抖。先止血再说。第一步kill掉从库的备份进程释放全局读锁# 找到备份进程psaux|grepxtrabackup# kill掉kill-9pid第二步重启Java应用等线程池释放GC恢复。从发现问题到恢复服务花了将近20分钟。说实话当时脑子一片空白走了不少弯路。如果监控更完善应该能更快定位。后来我怎么改的止血之后更得解决根因。不然下次还会踩。当时真的很后悔没早点换备份方案。FLUSH TABLES WITH READ LOCK是老方案了锁全库这个特性平时不觉得有问题一出事就是大事。后来换成了 XtraBackup备份期间不锁表从根上断了这个隐患# XtraBackup 热备份不需要全局锁xtrabackup--backup--target-dir/data/backup/然后加了备份监控。备份开始和结束都记录时间。超过预期时长立刻告警不能等出了事才查。连接超时也调了。从30秒降到10秒。之前设太长了请求排队30秒才超时积压量翻了好几倍。最后是告警分层。之前只盯CPU和数据库延迟线程池和内存都没监控。这次加上了线程池使用率80%就告警别等到100%才反应。我的教训回头看这次故障其实挺冤的。备份策略居然没评估过锁表影响。备份方案选型的时候只看了能不能备份成功没想过备份期间对业务有什么影响。这是最关键的失误。监控也缺了一大块。平时只盯CPU和数据库延迟线程池和内存根本没管。这次jstat的Full GC数据是排查的关键线索但平时根本没看过这个指标。连接超时也设太长了排队30秒才超时积压起来根本刹不住。还有从库读请求缺少降级机制。数据库一挂应用也跟着挂。如果应用侧有熔断至少写入不会受影响。排查的突破口是jstat的Full GC数据异常。顺着GC找到线程积压再顺着线程找到锁表。和上篇讲的思路一样先看现象再一层层追。避坑清单备份方案选型时先搞清楚备份期间数据库还能不能正常服务。不是能备份就行生产环境首选 XtraBackup 这类热备份工具备份期间不锁表连接超时设太久故障时请求会疯狂排队。积压比故障本身更致命线程池使用率 80% 就该告警等到 100% 服务已经挂了数据库超时要有熔断不能一个故障拖垮整套服务jstat 的 GC 数据别忽略异常时能帮你快速缩小排查范围备份任务要监控时长超时说明有问题不能等出了事才查告警要分层。CPU、线程池、内存、IO 都要覆盖只盯 CPU 会漏信号凌晨 3 点先止血拉服务根因白天再慢慢查。恢复永远优先排障不复盘的故障迟早会重演这次给我最深的教训是备份方案不能只看能不能备份成功。备份期间对业务的影响才是真正的评估重点。级联故障的触发条件往往很普通。一个备份任务一个锁表操作每个环节单独看都没什么大不了。但叠在一起系统就扛不住了。上篇讲了排查工具和方法。这篇讲了真实故障场景。两篇结合起来下次遇到CPU 100%就不慌了。我是数据库小学妹咱们下篇见