用心打造
VPS知识分享网站

MySQL主从复制延迟越来越大:延迟来源定位教程

MySQL副本的 Seconds_Behind_Source 从几秒升到几分钟,读写分离开始读到旧数据,备库也迟迟追不上。只盯着一个延迟数字容易误判,因为复制链路至少包含从源端接收binlog、写入relay log和在副本应用事务三个阶段。

处理重点是先确认卡在接收还是应用,再查造成该阶段吞吐不足的具体事务或资源。 不要一看到延迟就重启复制线程,重启会丢失最有价值的现场状态。

复制延迟

先确认延迟是否真实且持续

在副本上连续采样,而不是只执行一次:

SHOW REPLICA STATUS\G

重点记录 Replica_IO_RunningReplica_SQL_RunningSeconds_Behind_SourceLast_IO_ErrorLast_SQL_Error、源日志读取位置和relay log执行位置。两个线程通常都应为 Yes,错误字段应为空。

MySQL官方说明,Seconds_Behind_Source 为0通常表示副本追上,但网络中断尚未被检测、旧时间戳事件等情况会让这个值暂时失真。至少观察多个采样点,并同时比较日志位置和GTID进度。

判断是接收慢还是应用慢

如果I/O接收线程停掉或反复重连,优先检查源库连接、账号权限、TLS、网络和源端binlog是否还存在。若接收位置持续前进,而执行位置不动或差距扩大,瓶颈通常在副本应用阶段。

也可以查看Performance Schema复制表:

SELECT * FROM performance_schema.replication_connection_status\G
SELECT * FROM performance_schema.replication_applier_status_by_coordinator\G
SELECT * FROM performance_schema.replication_applier_status_by_worker\G

多线程副本要逐个查看worker,避免总状态看似运行,实际有一个worker被大事务或锁等待拖住。先把链路分段,才能把网络问题与SQL执行问题分开。

用GTID差集衡量未应用事务

启用GTID时,检查源库和副本的执行集合:

SELECT @@GLOBAL.gtid_executed;

把源端集合与副本集合放入 GTID_SUBTRACT(),可得到副本尚未执行的事务范围:

SELECT GTID_SUBTRACT('source_gtid_set', 'replica_gtid_set');

差集持续扩大说明写入速度长期高于副本应用能力;差集稳定缩小说明副本正在追赶。GTID字符串可能很长,生产环境应由监控程序采集,不要在业务高峰频繁输出全部内容。

GTID进度比单一秒数更接近复制事实,但它只说明数量范围,仍需结合事务大小和执行耗时。

查找阻塞应用线程的事务和锁

在副本检查当前线程与事务:

SHOW FULL PROCESSLIST;
SELECT * FROM performance_schema.data_lock_waits\G
SELECT * FROM information_schema.innodb_trx\G

长时间处于等待锁、执行DDL或扫描大量行的应用线程,会让后续事件排队。若副本允许报表查询,长查询也可能持有元数据锁或消耗I/O,间接拖慢复制。

不要直接 KILL 复制应用线程或删除relay log。先确认阻塞会话是否为非关键只读任务,再按业务窗口终止或迁移。解除阻塞后应看到执行位置继续前进,而不是仅看到线程重新变为Yes。

识别源库产生的大事务

一次批量更新数百万行,即使源库提交很快,副本仍要重放同等工作。结合源库慢日志、binlog时间段和发布记录,查找延迟开始前后的批处理、数据修复与大表DDL。

应用层应把可拆分操作按主键范围分批提交,并控制每批耗时与间隔。拆分不是越小越好,过多提交会增加日志和事务开销。目标是让单个事务可预测,避免一个超大事务独占应用线程。

行格式复制还会放大无索引更新的成本。检查副本表结构与索引是否和源库一致,尤其是用于定位行的主键或唯一键。

检查副本CPU、磁盘和内存

复制应用本质上仍是数据库写入,应同时观察系统资源:

vmstat 1 10
iostat -xz 1 10
pidstat -p $(pidof mysqld) 1 10

高磁盘延迟、CPU长期饱和、频繁Swap或脏页刷新都可能限制吞吐。副本硬件明显弱于源库时,写入高峰会自然形成积压。

不要只增加并行线程来掩盖存储瓶颈。 如果磁盘已饱和,更多worker可能放大随机I/O与锁竞争,应先确认资源余量和事务依赖关系。

谨慎调整并行复制

MySQL 8.4可通过 replica_parallel_workers 配置多线程应用,并使用合适的并行类型与提交顺序。修改前先查询现值和版本:

SHOW VARIABLES LIKE 'replica_parallel_workers';
SHOW VARIABLES LIKE 'replica_preserve_commit_order';

提升worker数量需要在测试环境压测,观察应用吞吐、CPU、I/O和锁等待。存在热点表或事务强依赖时,并行度不会线性提升。

可在 萤光云 创建同版本主从环境,也可借助 LightNode 复现跨区域链路。测试数据必须脱敏,并保持参数、表结构和写入模型与生产一致。

网络链路异常的处理方法

接收线程落后时,检查源库到副本的带宽、丢包、延迟与防火墙空闲超时。不要只从副本ping源库,复制连接可能经过专线、NAT或代理,路径与管理网络不同。

关注 Last_IO_Error、重连次数和Performance Schema中的连接状态。若源端已经清理副本仍需要的binlog,通常需要从新备份重建,不能靠反复 START REPLICA 找回已删除日志。

网络修复后的验收是接收位置稳定前进且不再重连,同时应用线程能够逐步缩小积压。

延迟恢复期间保护业务

副本严重落后时,应暂停把强一致读请求路由过去,并确认备份、报表和故障切换策略不会把旧副本误当成最新节点。必要时限制源端非关键批量写入,为副本追赶创造窗口。

不要在未核对GTID和数据一致性前强制提升副本为主库。复制线程运行不代表数据已经追平,故障切换必须以事务进度为依据。

建立可操作的延迟监控

监控应同时采集线程状态、秒级延迟、GTID或日志位置差、relay log大小、worker错误、磁盘延迟和CPU。告警要区分瞬时峰值与持续增长,例如连续多个周期上升再触发。

记录写入吞吐和延迟恢复速度,可以估算副本追平所需时间。好的告警不仅说延迟高,还应告诉值班人员卡在哪一段、是否仍在扩大。

常见问题

Seconds_Behind_Source为0就一定没有延迟吗?

不一定。网络中断尚未超时、线程状态异常或时间戳特殊时可能出现误导,应同时检查线程、错误和事务进度。

重启MySQL能让副本追得更快吗?

通常不能,还会丢失缓存并掩盖现场。应先定位接收、锁、大事务或资源瓶颈。

并行worker越多越好吗?

不是。并行度受CPU、存储、事务依赖和锁竞争限制,必须压测后逐步调整。

温馨提示

在生产环境调整复制参数或终止阻塞会话前,保存完整的 SHOW REPLICA STATUS、GTID集合和错误日志。任何可能改变复制位置的操作,都应先确认可用备份和明确回滚路径。

赞(0)
未经允许不得转载;国外VPS测评网 » MySQL主从复制延迟越来越大:延迟来源定位教程
分享到