症状
一行状态藏着一个双面故事: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()