MySQL运维设计实战:36小时崩而复稳
|
去年12月份那场MySQL宕机,我现在想起来都后怕——周四下午四点二十,监控大屏突然炸成一片红,告警短信跟放鞭炮似的往手机里钻,运维群里@我的消息直接刷到99+。当时我正在啃冷掉的咖啡,抬头看见值班室白板上的拓扑图,主库和两个从库全标着「UNAVAILABLE」,心里咯噔一下:这他妈要完。 第一反应是查慢查询日志,结果发现主库的IO线程卡在某个大事务上,锁等待时间已经飙到三百多秒。我原以为只是常规的锁冲突,结果翻到binlog才发现,有人把一个三千万行的表更新语句直接扔到了主库上——没有分批,没有索引优化,连WHERE条件都写得跟闹着玩似的。更绝的是,这个SQL是某个核心业务线的定时任务,每天下午四点整执行,而那天因为时钟同步问题,实际执行时间比平时晚了二十分钟,正好撞上业务高峰。 这时候指挥官在群里喊话:「先切从库!」我盯着从库的延迟监控,心说这他妈延迟都两万秒了,切过去也是白给。果然,切完不到三分钟,应用层开始报「Duplicate entry」错误——从库的数据早就跟主库对不上了。这时候工单系统突然弹出一条新请求:「用户反馈无法下单,请紧急处理」,我盯着屏幕上的「紧急」标签,突然想起上周刚把这类工单的优先级从P0降到P2,现在看来这决策简直像个笑话。 冷掉的咖啡喝到第三口,机房的噪音突然变得刺耳——空调出风口嗡嗡响,像极了主库宕机前那几秒的磁盘IO声。我翻出备用笔记本,准备搭临时集群,结果发现Docker镜像版本和线上环境差了三个大版本,pull下来要半小时。这时候运维小哥冲进来:「主库的磁盘空间满了!」我盯着df -h的输出,发现/var/lib/mysql目录下多了个三百G的日志文件——是某个开发偷偷开的general_log,开了两周没人发现。 周五凌晨两点,我们终于把数据从备份库恢复出来,结果发现备份是三天前的——因为备份脚本里有个隐藏的「--skip-lock-tables」参数,导致备份时数据不一致。这时候测试环境突然报错,原来是某个QA同学为了测性能,把临时表的max_heap_table_size调到了1G,结果生产环境的临时表全堆在内存里,直接把MySQL进程撑爆了。我盯着error log里的「Out of memory」错误,突然想起上个月刚拒绝过运维组申请的「给MySQL服务器加内存」的工单——当时觉得32G够用了,现在看来这决策比工单系统的优先级调整更傻逼。 周五中午十二点,系统终于恢复,但业务线已经炸了锅。运营同学在群里发战报:「昨日GMV同比下降67%」,财务同学私聊我:「这损失算谁的?」我盯着屏幕上的数字,突然想起上周五的架构评审会——当时有人提议把核心业务拆成微服务,用多主架构提高可用性,结果被CTO以「成本太高」为由否了。现在看来,这成本算得可真他妈「精准」。 这场事故最魔幻的地方在于,所有问题都不是新出现的:慢查询、大事务、无索引、备份失效、配置错误、资源不足——这些问题在之前的监控报告里都出现过,但没人当回事。就像运维老王说的:「我们就像在高速公路上修车,车轱辘都掉了,还在讨论该用哪个牌子的螺丝刀。」 后来复盘时,我发现一个有趣的现象:出问题的SQL里,有70%是三年前写的,30%是最近一个月新加的;而优化过的SQL里,90%是最近半年重构的。这让我突然意识到,MySQL运维的「优胜劣汰」法则比达尔文的更残酷——不是最强的代码活下来,而是最近被改过的代码活下来。因为只有被改过的代码,才会被重新审视、被优化、被加监控;而那些「稳定运行」的老代码,反而成了定时炸弹,因为没人敢动它,也没人记得它到底在干什么。
文章配图,仅供参考 现在我们的监控系统里多了个「代码年龄」指标——任何超过一年没改过的SQL,都会被标记为「高风险」,强制要求重构。有人说这太激进,但我觉得这他妈才是真正的「防御性编程」——不是防bug,是防人,防那些觉得「稳定=不用改」的傻逼。上周五,我又收到一个工单:「用户反馈查询变慢,请优化」。我点开SQL一看,是个五年前的老代码,WHERE条件里连索引都没用。我直接回了句:「这个SQL太老了,重构前先加监控,出了问题别找我。」结果业务方回:「但之前一直没问题啊。」我盯着屏幕上的回复,突然想起那场36小时的宕机——有些问题,不是没出现,只是时候未到。 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


DBA熬夜改表?这本MySQL手册让设计运维一步到位
交互设计:以独特性铸就体验防线
运维老手血泪总结:5个Java服务器部署深坑
Unix调试总卡壳?14年老运维揭五大隐性陷阱
14年运维实战:客户端云部署与网络优化跃迁
无障碍设计:从首行代码践行技术尊重
后端站长的视觉设计与性能优化平衡术
