MySQL运维与设计五大致命陷阱揭秘
|
凌晨三点二十,机房空调嗡嗡响得像快散架的拖拉机,我盯着监控屏右下角那块胶布——上周贴上去遮住裂了的像素点,现在它翘起个边,微微颤着。值班室泡面桶堆在脚边,红烧牛肉味混着机柜散热的铁腥气。我刚咽下半口面,手机震起来,是小陈:“哥,从库IO线程挂了,show slave status全null。” 我原以为只是网络抖动。结果连上跳板机一查,主库binlog里最后一条是“2025年5月七号上午十点零三分”,之后十六个小时空白。十六小时。不是秒,不是分,是整整十六个小时。没人动过主库,没人删过日志,也没人设过expire_logs_days——它自己停了。就那么静静躺着,像装死。
文章配图,仅供参考 第二天早上九点四十七,老板在运维大群发了个截图:一张钉钉工单,标题写着“客户投诉订单不更新”,下面三行字:“已联系DBA”、“待处理”、“优先级:中”。他没说话,就甩了这页。我盯着那“中”字看了四十来分钟,直到小王端着保温杯凑过来,嘬一口枸杞水:“老张,你那套‘双写+校验’逻辑,真能扛住半同步超时?”。我没答。我知道他指哪——去年十月那个半夜丢两单的事,我们吵了两小时,最后把semi_sync_timeout从10秒调到3秒,还加了retry机制。结果呢?这次根本没进retry分支,直接走主库返回了脏读。主库自己都懵着,哪来的commit确认。窗外雨下得没停过,水痕在玻璃上斜着爬。我翻出五月七号的备份记录,看到那个熟悉的cron条目:/backup/mysql_full.sh >> /var/log/backup.log 2>&1。可log文件最后一行是“2025-05-06 23:59:58 Start full backup”,后面空了。不是失败,不是报错,是空的。像有人拿橡皮擦,把后半截全抹掉了。备份脚本自己都没活到零点。我抓起电话打给IDC——那边说他们监控显示存储节点IO wait峰值卡在99.7%连续四十一分钟。谁定的阈值?我不知道。谁该盯这个?我原以为运维组每人都有这个告警的飞书订阅。结果查了一圈,只有老李的钉钉开了通知,但他手机静音。他孩子昨天打来电话问“爸爸为什么总不接视频”,我没好意思细问是不是又因为静音漏了告警。 磁盘满这事吧……说来真没劲。不是爆在data目录,是爆在/tmp。临时表太多,没设tmp_table_size,更没配max_heap_table_size——就图省事留默认值。某天凌晨两点十七,一个报表查询扫了八张关联表,生成3.2GB临时表,/tmp撑爆,整个实例卡住。不是OOM,不是crash,就是不动。show processlist全是Sleep,但state是“Writing to tmp table”。客服打来电话:“用户说下单按钮一直转圈”,我说“稍等”,挂掉,敲了句kill -9,重开mysqld。重启前我顺手df -h,发现/tmp用了99%,而/data还剩41%。我盯着这数字看了七秒,没动。就七秒。然后按回车。 还有一次迁移丢数据。不是跨版本,是同版本主从切换。我们用pt-table-checksum校验了三次,checksum结果一致。可业务方上线后说,五月六号下午三点到四点之间的充值记录少了17条。我查了所有binlog、relay-log、甚至翻了应用层埋点日志——那段时间MySQL慢日志里压根没这条SQL。后来小刘蹲在机房角落啃冷馒头,忽然抬头说:“会不会是那个自动重试中间件……没传回主键?”我愣住。对,那个重试逻辑写了两年多,从来没动过,也没人看。它把“INSERT IGNORE”当成功处理,实际主库唯一键冲突,返回了0 affected rows,但它照样发ACK。我查了那17条记录的手机号,全撞在同一个渠道ID上。渠道系统凌晨做了灰度,新增了去重规则。我们的人不知道,中间件也不知道,MySQL当然更不知道。它只是按协议,老老实实执行了语句,然后返回了状态码。 说到证书……上个月DNS服务商API接口崩了两小时,导致我们的Let’s Encrypt续期脚本取不到ACME域名验证记录。但没人想到这会影响MySQL——因为我们把SSL证书和Web服务混放在同一台Nginx反向代理后面。MySQL客户端连接用的是IP直连,根本不用证书。可那天刚好有批安卓APP升级了TLS 1.3强制策略,所有流量被Nginx拦截再转发。Nginx证书过期了三分钟,下游MySQL连接池开始疯狂报“SSL handshake failed”。我们排查到Nginx配置之前,已经干掉了两轮主库连接数。老赵在机房门口骂了十五分钟脏话,声音盖过了空调噪音。最后发现原因,他掏出手机拍下证书过期时间,发到群里,只写了仨字:“我瞎了。” 其实最吓人的不是宕机,是没告警。我们所有核心库的磁盘使用率监控阈值是90%。可/dev/sdb1挂的是binlog专用盘,监控脚本里写的是sda1。写错了。三年了。没人核对过dev名映射。就靠肉眼巡检。我上一次搬家时整理旧硬盘,翻出2018年的监控部署文档,第一页就写着“建议使用lsblk -f输出比对设备名”,我那时还用荧光笔画了横线。现在那块硬盘躺在抽屉最底下,灰尘厚得能写字。 明天先把告警阈值调了。把sdb1加上。顺便看看谁还在用mysql_real_escape_string拼SQL。还有,问问小陈他孩子睡了吗——昨晚上那通电话,他声音哑得不像三十岁的人。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


Android存储优化实战:14年运维经验驱动秒开体验
信息流设计新人5大隐形坑:第3个90%人忽略的AI安全漏洞
站长必避的3个MySQL设计陷阱:半年一崩
MySQL高可用运维设计:站长全栈实战路径
创业信息流导航设计:流量×合规×运营三角平衡术
CSS艺术家眼中的MySQL:设计即运维,一册搞定
MySQL运维设计实战:36小时崩溃到稳如磐石