Relay_Log_Space持续暴涨但Exec_Master_Log_Pos几乎不动,说明SQL线程卡死未消费中继日志;需结合Relay_Log_Space大小、Read/Exec位点差值及磁盘空间综合判断。

怎么看 relay log 是否堆积严重
Relay_Log_Space 持续暴涨但 Exec_Master_Log_Pos 几乎不动,说明 SQL 线程根本没在消费 relay log。这不是网络或主库问题,而是从库回放卡死的明确信号。别只盯着 Seconds_Behind_Master,它可能显示为 0 或 NULL,但中继日志已占满几十 GB。
-
SHOW SLAVE STATUS\G中Relay_Log_Space超过 5GB 就该警觉;超过 20GB 基本确认 SQL 线程长期停滞 - 对比
Read_Master_Log_Pos和Exec_Master_Log_Pos差值:若差值稳定在几百万甚至上千万字节,说明 relay log 已写满、SQL 却原地不动 - 检查磁盘空间:
df -h /path/to/relay-log-dir,避免因空间不足导致 IO 线程退化为阻塞写
怎么用 mysqlbinlog 解析 relay log 定位大事务
从库上的 relay log 是压缩后的二进制日志,和主库 binlog 格式一致,可用 mysqlbinlog 直接解析。重点不是看语句多不多,而是看事务跨度——单个事务从 ### BEGIN 到 ### COMMIT 之间夹了多少行变更。
- 先查当前 relay log 文件:
SHOW SLAVE STATUS\G中的Relay_Log_File - 解析命令示例:
mysqlbinlog --no-defaults --base64-output=decode-rows -v /var/lib/mysql/relay-bin.000015 | grep -A 5 -B 5 "### BEGIN" - 重点关注:事务内是否含跨百张表的
### UPDATE、是否出现未走索引的全表扫描(WHERE条件无索引)、是否包含ALTER TABLE或TRUNCATE - 注意时间戳:同一事务内首条 event 和最后一条 event 的
# at位置差值过大(比如超 5MB),大概率是分表批量插入类操作
为什么解析出的大事务在从库执行特别慢
主库并行写的事务,到从库变成单线程串行回放,放大了锁等待和 I/O 压力。即使开了并行复制(slave_parallel_type = 'logical_clock'),单一大事务仍强制走单线程。
- 事务锁表:从库回放时遇到
Waiting for table metadata lock,说明有 DDL 正在执行,或长事务未提交 - 刷脏页压力:事务修改大量行 → InnoDB 频繁刷脏页 →
innodb_io_capacity不足时会拖慢整个 SQL 线程 - 索引缺失:主库有覆盖索引,但从库表结构不一致(如缺少二级索引),导致回放时
UPDATE变成全表扫描 - 参数影响:若
sync_relay_log = 1,每事务都fdatasyncrelay log,IO 线程本身变慢,间接导致 relay log 积压,进一步挤压 SQL 线程资源
怎样快速确认是不是 relay log 写盘拖慢了整个链路
IO 线程写 relay log 是单点瓶颈,尤其当磁盘 IOPS 不足或 sync_relay_log 设为 1 时。此时 Read_Master_Log_Pos 更新缓慢,但 Slave_IO_Running 显示 Yes,容易误判为网络问题。
- 用
iotop -p $(pgrep mysqld)找出 MySQL 进程内高 IO 的 LWP(轻量级进程),再结合SHOW PROCESSLIST查system user对应的ID,确认是否为 IO 线程 - 查系统调用:
strace -p,若频繁出现-e trace=fdatasync,write fdatasync(50)且耗时长,基本锁定sync_relay_log = 1导致 - 临时验证:设
SET GLOBAL sync_relay_log = 10000(每万次事务刷一次),观察Read_Master_Log_Pos推进速度是否明显加快 - 注意副作用:该调整降低可靠性,仅用于定位;生产环境建议配合
sync_relay_log_period = 1000平衡
真实延迟常藏在 relay log 的字节差值和 fdatasync 调用里,而不是告警数字上。分析时优先看 Relay_Log_Space 和 Read/Exec 位置差,再决定是查事务内容还是查 IO 行为——这两步跳过,后面所有优化都是蒙眼调参。











