MySQL binlog 占满磁盘?一次紧急清理笔记
凌晨 2 点 17 分,手机突然疯狂震动——监控系统报警:生产环境 MySQL 服务器磁盘使用率 98%!作为团队里唯一醒着的人,我不得不顶着困意爬起来处理这个突如其来的状况。今天就把这次惊心动魄的排障经历完整记录下来。
一、问题现象:磁盘空间去哪了?
登录服务器后,我首先用 df -h
确认了磁盘情况:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 50G 48G 1.2G 98% /
接着用 du -sh *
排查大文件,发现 /var/lib/mysql
目录占用了 42G!进一步检查发现是 binlog 文件爆炸式增长:
-rw-r----- 1 mysql mysql 1.1G Mar 15 00:00 mysql-bin.000341
-rw-r----- 1 mysql mysql 1.1G Mar 15 02:00 mysql-bin.000342
...
短短 2 小时就生成了 2 个 1.1G 的 binlog,这明显不正常。
二、紧急处理:先止血再治病
在业务高峰期直接清理 binlog 风险太大,我采取了分步方案:
- 临时扩容:联系运维紧急挂载 100G 临时磁盘,缓解燃眉之急
- 暂停同步:临时关闭从库同步避免连锁反应
- 安全清理:使用
PURGE BINARY LOGS TO 'mysql-bin.000340'
保留最近 2 天的日志
清理后磁盘使用率降至 65%,系统暂时恢复稳定。
三、根因分析:谁在疯狂写日志?
通过 SHOW MASTER STATUS
查看写入位置,结合 mysqlbinlog
工具分析内容:
# 查看当前写入位置
SHOW MASTER STATUS;
# 解析binlog内容
mysqlbinlog --start-datetime="2023-03-15 00:00:00"
--stop-datetime="2023-03-15 02:00:00"
mysql-bin.000341 | head -n 50
发现大量 UPDATE user_log SET status=1 WHERE id BETWEEN x AND y
语句——原来是新上线的批量状态更新功能没有分批处理,单次操作更新了 50 万条记录!
四、彻底解决方案
次日与开发团队讨论后,我们实施了以下改进:
- 优化批处理:将大事务拆分为每次处理 1000 条的小事务
- 调整 binlog 配置:
# 设置日志保留3天(原为默认30天) expire_logs_days = 3 # 限制单个日志文件大小 max_binlog_size = 500M
- 增加监控:对 binlog 增长速率设置告警阈值
五、经验总结
这次事故让我深刻认识到:
- MySQL 的默认配置不一定适合生产环境
- 批量操作必须考虑对日志系统的影响
- 磁盘监控不能只看使用量,还要关注增长速度
最后分享一个实用命令:SHOW BINARY LOGS
可以快速查看所有 binlog 文件及大小,建议加入日常巡检清单。
你有遇到过类似的坑吗?欢迎在评论区分享你的故事~
半夜处理生产事故太真实了,心疼楼主3秒钟 😢
学到了,max_binlog_size这个参数确实很实用,回头就加到我们服务器上
遇到过类似问题,我们是因为开发环境忘记关binlog导致测试服务器炸了,简直社死现场
楼主处理得很专业啊!换我可能就直接删binlog了,完全没想到先扩容再清理的稳妥方案
50万条记录一次性更新…这开发是想搞事情吧?建议让当事人请客吃饭赔罪