seconds_behind_master突增需先确认是否真实延迟:检查show slave status中seconds_behind_master持续上升、io/sql线程均运行正常、read_master_log_pos与exec_master_log_pos差距大;再定位大事务、binlog格式、relay log元数据及并行复制配置。

查 Seconds_Behind_Master 为什么突然变大
复制延迟突增,第一反应不是重启或跳过,而是确认它是否真实存在。很多情况下 Seconds_Behind_Master 显示几百秒,但实际只是主从网络抖动、从库 IO 线程短暂卡住,或主库 binlog 刷盘慢导致的假象。
先执行:
SHOW SLAVE STATUSG
,重点看三处:
-
Seconds_Behind_Master非 NULL 且持续上升 → 真延迟 -
Slave_IO_Running: Yes且Slave_SQL_Running: Yes→ 复制线程没挂,问题在 SQL 线程执行层 -
Exec_Master_Log_Pos和Read_Master_Log_Pos差距极大 → IO 线程拉得慢,可能是主库压力大、网络丢包、或从库磁盘 I/O 延迟高
定位是不是大事务在拖慢 SQL 线程
mysql 5.7+ 的单线程复制(slave_parallel_type = database 或未启用并行复制)下,一个大事务会阻塞后续所有事务执行,哪怕它只占 1% 的变更量,也可能让延迟堆积几十分钟。
在从库上查正在执行的复制事务:
select * FROM performance_schema.Events_transactions_current WHERE EVENT_NAME = 'transaction' AND STATE = 'COMMITTING';
再结合 information_schema.INNODB_TRX 查长时间未提交的事务。
- 如果
TRX_ROWS_MODIFIED> 100000,基本就是它了 - 注意
TRX_STARTED时间戳,和SHOW SLAVE STATUS里Exec_Master_Log_Pos对应的 binlog 位置比对,确认是否卡在这个事务上 - 别直接
KILL—— 可能触发回滚风暴;优先用STOP SLAVE+ 等待它自然提交/回滚,再START SLAVE
检查 binlog 格式和大事务写入方式
binlog_format = STATEMENT 时,某些函数(如 NOW()、UUID()、用户变量)会导致从库执行结果不一致,SQL 线程可能反复重试或卡死;而 ROW 格式下,大事务会产生巨量 binlog event,从库解析 + 应用压力陡增。
- 用
SHOW VARIABLES LIKE 'binlog_format';确认格式 - 查主库最近的大事务:抓取
mysqlbinlog --base64-output=DECODE-ROWS -v输出,看单个GTID_LOG_EVENT后是否跟着数十万行WRITE_ROWS_EVENT - 应用端若用
INSERT ... SELECT或LOAD DATA INFILE写入,务必加SET session binlog_row_image = MINIMAL;(5.6+)减少日志体积
监控和预防:别等延迟爆了才看
靠人工查 SHOW SLAVE STATUS 永远是被动响应。真正有效的做法,是把几个关键指标变成可告警的数字。
- 采集
Seconds_Behind_Master+Read_Master_Log_Pos–Exec_Master_Log_Pos(即 relay log 落后字节数),后者比前者更稳定,不受主库时钟影响 - 定期查
SELECT count(*) FROM mysql.slave_relay_log_info;—— 如果这个表为空或更新时间停滞,说明relay_log_info_repository = table没生效,复制元数据可能丢失 - 主库开启
long_query_time = 1+log_slow_slave_statements = ON,让从库慢查询也进 slow log,方便回溯
大事务本身不可怕,可怕的是它在复制链路里变成单点瓶颈。最常被忽略的一点:即使开了并行复制(slave_parallel_workers > 0),只要事务跨库、或用了 autocommit=0 手动事务,依然会退化为串行执行。