不是真延迟,Seconds_Behind_Master > 0但SQL线程在运行时,可能因大事务阻塞、时钟不同步或单点卡顿导致数值失真;需结合Read_Master_Log_Pos与Exec_Master_Log_Pos差值、pt-heartbeat及worker状态综合判断。

Seconds_Behind_Master不归零,但SQL线程在跑,是真延迟吗?
不是所有Seconds_Behind_Master > 0都代表真实同步滞后。这个值只取当前正在执行的事务在主库写入时的时间戳,和从库系统时间做差——如果SQL线程卡在一个20分钟的UPDATE上,它就一直显示“几百秒”,哪怕relay log早已拉完。
先确认真实瓶颈:
- 查
SHOW SLAVE STATUS\G里Read_Master_Log_Pos和Exec_Master_Log_Pos是否持续拉开(IO拉得快、SQL追得慢) - 看
Relay_Log_Space是否稳定增长(增长慢说明IO卡住) - 执行
SELECT * FROM performance_schema.replication_applier_status_by_worker;,重点看LAST_ERROR_MESSAGE和WORKER_ID对应状态
开了slave_parallel_workers=8,为什么还是单线程回放?
并行复制不是设了线程数就自动生效的,它依赖主从两端的协同机制。常见失效场景:
- 主库
binlog_format不是ROW→ 切成ROW再重启主库mysqld(STATEMENT/MIXED下LOGICAL_CLOCK直接退化为串行) - 主库没启用组提交 → 检查
binlog_group_commit_sync_delay是否为0,且binlog_transaction_dependency_tracking必须是COMMIT_ORDER(MySQL 5.7+默认)或WRITESET(MySQL 8.0+推荐) - 从库
slave_parallel_type仍是DATABASE→ 改成LOGICAL_CLOCK(5.7)或WRITESET(8.0),改完要STOP SLAVE; START SLAVE; - 事务含
LOCK TABLES或操作MyISAM表 → 这类语句会打断事务依赖链,整个worker池被阻塞
innodb_flush_log_at_trx_commit和sync_binlog怎么配才不拖慢从库?
从库不需要和主库一样强一致刷盘。主库设1是为了崩溃不丢事务;从库只要保证relay log不丢,靠relay_log_recovery=ON就能恢复。
生产常用折中方案:
- 从库设
innodb_flush_log_at_trx_commit=2(每秒刷redo) +sync_binlog=1000(每1000次事务刷binlog)→ 显著降低I/O压力,延迟波动变大但可接受 - 绝对禁止
sync_binlog=1搭配innodb_flush_log_at_trx_commit=2→ 主库会因组提交机制卡住,TPS暴跌,间接拉长从库追赶时间 - 检查当前值:
SELECT @@sync_binlog, @@innodb_flush_log_at_trx_commit;
大事务一来,所有并行线程全卡住,怎么办?
这是InnoDB并行复制最硬的限制:同一张表的DML必须串行回放,避免冲突。一个未拆分的百万行UPDATE t1 SET x=1,会让全部slave_parallel_workers干等。
解决路径很实际:
- 主库端拆事务:用
WHERE id BETWEEN ? AND ?分批次提交,每批≤5000行 - 避免在业务高峰期执行大DDL(如
ALTER TABLE加索引),这类操作在从库也是单线程重放 - 确认表有主键或唯一索引 → 没有的话,
ROW格式下的更新会变成全表扫描式回放,进一步拖慢 - 监控长期运行事务:
SHOW PROCESSLIST里找Updating或Waiting for dependent transaction状态
真实延迟往往藏在“看起来正常”的细节里:比如Seconds_Behind_Master跳到0,但Exec_Master_Log_Pos不动;或者replication_applier_status_by_worker里多个worker显示Waiting for an event from coordinator——那大概率是主库压根没发出来可并行的事务组,而不是从库没力气跑。


















