← 中文资源

简体中文版本

MySQL — 复制延迟:Seconds_Behind_Master 持续增长

用 SHOW REPLICA STATUS 与 performance_schema 诊断增长的 MySQL 复制延迟,区分 IO 线程与 SQL 线程停滞,并修复瓶颈侧。

阅读英文原文

症状

  一行状态藏着一个双面故事:Seconds_Behind_Master 高达 1873 秒,而 Retrieved_Gtid_Set 与 Executed_Gtid_Set 相差二十多万个事务——IO 线程健康,中继日志里堆着货,瓶颈是应用线程。两个线程都显示 Yes,这正是健康检查全过而用户看到陈旧数据的原因。反过来 Retrieved 勉强领先 Executed 时,问题在网络或主库投递。业务时段延迟爬升且永不追平、副本读不到主库已可见的写入,是吞吐失配的外显。

诊断思路

  先完整读 SHOW REPLICA STATUS,比较 Retrieved 与 Executed 位置判断瓶颈侧;再看 applier 线程状态(system user 行是“从日志读事件”还是“执行中”);最后查副本磁盘压力(Innodb_data_pending 与 iostat),应用窗口期磁盘饱和就不是并行度问题而是 IO 争用。主库夜间批量任务造成突发写入超过稳态应用速率,是常见的节奏性失配。

根因

  复制延迟本质是吞吐失配:主库以全并行写入,副本以受限的 applier 并行度或饱和 IO 应用。持续写入速率超过应用速率时,已执行位 点持续落后,Seconds_Behind_Master 无界增长。

修复与验证

  开启并调优并行复制:replica_parallel_workers=8、replica_parallel_type=LOGICAL_CLOCK、主库 binlog_transaction_dependency_tracking=WRITESET 让依赖可并行。修主库写入形状——applier 只能重放它收到的东西,20 万行的大事务会让应用全程停摆,改成 5000 行有界批提交让并行 applier 交错执行。保护副本 IO 预算:分析读迁到别的副本,先查 InnoDB pending IO 再怪并行度。验证时同等写入负载下延迟冲高后有界回落到零,趋势告警在整周业务时段保持安静。注意 DDL 与外键无论如何都会串行化 applier——写形状与并行度要一起修。

代码示例

mysql> SHOW REPLICA STATUS\G
     Replica_IO_Running: Yes
    Replica_SQL_Running: Yes
Seconds_Behind_Master: 1873
     Retrieved_Gtid_Set: 3e11...:1-98421132
     Executed_Gtid_Set:  3e11...:1-98214355
# my.cnf on the replica
replica_parallel_workers = 8
replica_parallel_type = LOGICAL_CLOCK
binlog_transaction_dependency_tracking = WRITESET
# one 200k-row transaction stalls apply for its whole duration;
# bounded batches let the parallel applier interleave:
for batch in chunked(rows, size=5000):
    conn.begin()
    upsert(conn, batch)
    conn.commit()