binlog 暴涨 500G?一次从磁盘告警到定位重试风暴的完整复盘

binlog 暴涨 500G?一次从磁盘告警到定位重试风暴的完整复盘

上周处理了一次 binlog 暴涨,记录一下,也算给自己留个复盘。文末附上为此写的离线小工具,需要自取。

一、事故现场

早上八点收到磁盘告警,心里咯噔一下。登上控制台一看,binlog 3 天内涨了 500G+,已经挤到备份空间。第一反应是把误操作大事务的锅先按住,然后开始排查。

先看了一个最近的 binlog 文件切片,发现一个反常现象:

一个 65MB 的 binlog 文件,时间跨度只覆盖了 12 秒业务。

正常业务即使高峰期,一个 64MB 的切片怎么也能覆盖几分钟。12 秒就刷满 65MB,说明这 12 秒里发生了一些"不正常的事"。

二、先说结论(赶时间的看这里)

  • 97% 的 binlog 空间(63.5MB)被同一张表的 17 次 UPDATE 占满,平均单条 3.9MB
  • 根因:某同步任务失败后进入重试风暴,每次重试都把一份 ~1MB 的 HTML 错误日志整体回写到同一行的错误详情字段
  • 最极端时,同一行在 8 秒内被更新 26 次
  • 修复:修掉同步任务的重试逻辑(失败快照落文件而非回写数据库),binlog 生成速率恢复正常

三、排查过程

3.1 常规手段为什么不够用

第一反应是 mysqlbinlog 直接翻。说实话一开始方向跑偏了:我怀疑是哪个批量任务抽风,朝那个方向翻了一阵没结果,绕了半小时才回头从 binlog 本身下手。但很快发现这条路也走不通:

  • ROW 格式 binlog 里全是行镜像事件,mysqlbinlog 只能"翻译",几十万条事件人肉翻不现实
  • SHOW BINLOG EVENTS 同样只给事件列表,不给体量统计
  • 问题本质是"谁在刷盘",需要一个按表、按行聚合的分析视角,光靠逐条看事件不行。

3.2 我的排查思路

绕了弯路之后,干脆自己写个脚本聚合,按这个思路拆解:

  1. 表级写入排行:每个 ROWS 事件都有 table map,按表聚合事件字节数,立刻知道"钱花在哪了"
  2. 热点行统计:同一行(主键相同)被反复 UPDATE 的次数,应用 bug、空转、重试风暴,在这一项上全都现形
  3. 大字段摘要:ROW 镜像里超长字段只报体积不报内容(如 col14=<65537 B>),定位"什么字段在塞大数据"
  4. 大事务排行:单事件超大写入直接排出来

按这个思路跑完 65MB 切片,报告第一行就是:

jobctl.sync_error_payload   UPD: 34 次   bytes: 66,259,266   evt: 130

单表占了全文件 97% 的写入量。再看热点行:同一行主键在 8 秒内被更新 26 次,每次写入 1MB 左右的大字段。高频、同行、大字段整体回写,重试风暴的特征全齐了。

3.3 顺藤摸瓜

拿着"表 + 频率 + 单次写入大小"去找应用同学,几句话就对上了。那个同步任务前一天开始失败,框架的通用重试逻辑把完整的 HTML 错误页(含堆栈、请求体)作为错误详情写回了数据库行,而且失败不会终止重试,于是形成了"失败 → 写 1MB → 再失败 → 再写 1MB"的死循环。

改法不复杂:错误快照落本地文件(或对象存储),数据库里只存引用路径;同时给重试加退避和熔断。改完第二天观察,binlog 生成速率回到正常水位。

四、复盘得到的经验

  1. binlog 暴涨先看"单文件时间跨度",切片越小、覆盖时间越短,说明写入越异常,这个比值比总量更早暴露问题
  2. ROW 格式下 mysqlbinlog 原生输出不适合做体量归因,按表/行聚合才是对的视角
  3. "同一行被反复刷"是应用层 bug 的强信号,重试风暴、缓存空转、计数器误写,都会留下这个指纹
  4. 错误详情不要塞数据库大字段,要落就落文件,库里存路径
  5. 长事务 + 高频 binlog 生成的组合,还会拖累 undo purge,放大问题(这次 binlog 膨胀和 purge lag 是叠加出现的)

五、顺手做了个工具

这次排查用的聚合脚本,后来整理成了一个离线小工具 binlog_analyze:

  • 纯 Python 标准库,零依赖、纯离线解析,不连数据库,对生产零影响
  • 输入一个 binlog 文件,几十秒输出报告:表级写入排行 / 反推等效 SQL / 热点行 TOP N / 高频语句 / 大事务排行 / 繁忙时段 / 异常信号
  • Windows 下打包了单文件 exe,双击即用;也附完整源码
  • 适配 MySQL 及兼容引擎(PolarDB、TDSQL、OceanBase MySQL、TaurusDB 等)的 ROW 格式 binlog

上面报告里的数据就来自它的输出(表名已脱敏)。

工具放在这里了,需要自取:
👉 https://mbd.pub/o/bread/YZaWk5hvaw==


posted @ 2026-10-29 15:13  lysheng  阅读(5)  评论(0)    收藏  举报