核心原因是FTWRL会挂起从库SQL线程,导致relay log堆积、Seconds_Behind_Master飙升;解决方法是备份前STOP SLAVE SQL_THREAD,备份后START SLAVE SQL_THREAD并验证延迟归零。

从库备份时 flush tables with read lock 会阻塞 SQL 线程
夜间备份导致主从延迟飙升,核心原因不是“备份慢”,而是 mysqldump 或 xtrabackup 在启动阶段执行的 FLUSH TABLES WITH READ LOCK(FTWRL)会直接挂起从库的 SQL thread。该锁在从库上不只影响 DML,还会让 SQL 线程暂停回放 relay log,而 IO 线程仍在接收 binlog —— relay log 持续堆积,Seconds_Behind_Master 就开始线性上涨。
mysqldump 默认 --single-transaction 不适用于从库
很多人误以为加了 --single-transaction 就能避免锁,但它只对 InnoDB 表生效,且依赖 MVCC 快照;而从库上 SQL thread 正在执行的事务可能持有元数据锁(MDL),或正在回放涉及 MyISAM 表、DDL、或显式 LOCK TABLES 的语句 —— 这些都会让 FTWRL 等待,最终触发超时或强制阻塞。
-
mysqldump --single-transaction在从库上仍可能触发 FTWRL(尤其当存在非 InnoDB 表或未提交事务时) -
xtrabackup --slave-info虽不显式加锁,但其内部LOCK BINLOG FOR BACKUP(MySQL 8.0.26+)或早期版本的 FTWRL 同样会卡住 SQL 线程 - 备份工具若未指定
--no-lock或跳过锁逻辑(如用xtrabackup --no-lock --safe-slave-backup),默认行为就是锁表
backup 过程中 relay log 写入和读取竞争磁盘 I/O
即使锁已释放,备份进程本身也会大量读取 ibdata、ib_logfile 和 relay log 文件,与 SQL 线程争抢磁盘带宽。尤其当从库使用机械硬盘或未配置独立 I/O 路径时,Relay_Log_Space 持续增长、Slave_SQL_Running_State 长时间停留在 Reading event from the relay log 或 Waiting for commit lock,都是 I/O 瓶颈的典型信号。
- 监控指标:检查
SHOW SLAVE STATUS\G中的Relay_Log_Space是否在备份期间陡增 - 系统层面:用
iostat -x 1观察%util和await,若await > 20ms且持续超 5 分钟,基本可判定 I/O 饱和 - 规避方式:将
relay-log和datadir分开挂载到不同物理盘(例如 SSD 存 relay log,NVMe 存数据文件)
真正安全的夜间备份必须绕开 SQL 线程阻塞
不要依赖“备份时间短就没事”——哪怕只锁 3 秒,如果主库那秒刚好提交一个大事务,从库就要等它完整回放完才能继续,延迟可能放大数十倍。生产环境唯一稳妥的做法是:在备份前临时停掉 SQL 线程,备份完成后再启动,并确认 Seconds_Behind_Master 回落为 0。
- 停复制:
STOP SLAVE SQL_THREAD; - 执行备份(此时 IO_THREAD 仍在拉 binlog,relay log 不会丢)
- 恢复复制:
START SLAVE SQL_THREAD; - 验证:
SELECT TIMESTAMPDIFF(SECOND, NOW(), (SELECT @@server_id)) AS delay_check;不够准,应看Seconds_Behind_Master是否稳定归零
这个操作看似简单,但容易被忽略的是:必须确保备份窗口内主库没有执行 DDL 或跨库事务(否则 START SLAVE 可能报错),且从库 relay-log 文件不能被轮转(expire_logs_days 设置需大于备份周期)。


















