基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

MySQL主从延迟常见原因有哪些?

知识点图片

MySQL主从延迟(Replication Lag)是生产环境中非常常见的问题。要理解延迟的原因,首先要知道延迟通常发生在从库的 SQL 线程回放 Relay Log(中继日志)的过程中。

MySQL 主从延迟的常见原因可以归结为以下几个核心维度:

1. 主库并发高,从库单线程回放(架构设计瓶颈)

  • 原因:主库上可能有多个客户端并发执行写操作,但在较早版本的 MySQL(5.6 之前)中,从库的 SQL 线程是单线程的。即使在 MySQL 5.7+ 引入了多线程复制(MTS,基于逻辑时钟或数据库/表级别),如果并发事务集中在同一张表或存在依赖关系,从库依然会退化为串行回放。
  • 现象:主库 TPS 很高时,从库的回放速度跟不上主库的写入速度,导致延迟不断累积。

2. 存在大事务(Large Transactions)

  • 原因:如果主库执行了一个耗时非常久的事务(例如一次性 DELETEUPDATEINSERT 几百万条数据),这个事务在主库上执行了 5 分钟,那么写入 Binlog 并传到从库后,从库的 SQL 线程也至少需要执行 5 分钟。在这 5 分钟内,后续的所有 Binlog 都要排队等待。
  • 建议:在业务中应避免大事务,大批量数据的修改应分批次进行(例如每次处理 1000-5000 行)。

3. 表缺乏主键或唯一索引(ROW 格式下的灾难)

  • 原因:在 MySQL 默认的 binlog_format=ROW 模式下,Binlog 记录的是每一行数据的物理变化。如果被更新的表没有主键或合适的索引,主库执行一条 UPDATE 可能利用了某些条件,但在从库回放时,由于是按行匹配,如果没有主键,从库会对发生变化的每一行数据都进行一次全表扫描
  • 现象:主库执行极快,但从库 CPU 和 IO 瞬间被打满,延迟呈指数级上升。

4. 执行了耗时的 DDL 操作

  • 原因:在主库对大表执行 ALTER TABLE(如加减字段、加索引)时,主库可能需要花费很长时间(如果未使用 Gh-ost / pt-osc 等在线 DDL 工具)。当这个 DDL 传到从库时,从库同样需要执行那么长时间,且 DDL 通常会独占操作,导致后续的 DML 操作全部阻塞。

5. 从库被长时间查询阻塞(锁冲突)

  • 原因:从库通常用于读写分离中的“读”节点。如果从库上正在执行非常耗时的慢查询(如复杂报表统计、大表联查),且这些查询触及到了主库正在同步更新的表,就会产生元数据锁(MDL Lock)冲突行锁等待
  • 现象:SQL 线程被阻塞,状态显示为 Waiting for table metadata lock 等,导致同步暂停。

6. 主从硬件差异或从库负载过高

  • 原因
    • 硬件差异:为了节约成本,从库的机器配置(CPU、内存、磁盘 IOPS)往往低于主库(比如主库用 NVMe SSD,从库用普通 SSD 甚至 HDD)。
    • 负载过高:从库可能除了承担日常读流量,还被用来做全量数据备份(如 mysqldump)、跑大数据量抽取的任务,导致 CPU 或磁盘 IO 跑满,无法及时回放 Relay Log。

7. 网络延迟

  • 原因:主库和从库跨机房、跨可用区(AZ)甚至跨地域部署,或者主从之间的网络带宽被其他业务打满,导致主库的 Binlog 传输到从库(IO 线程)的过程变慢。
  • 现象:这种情况较少见,通常表现为从库的 IO 线程延迟,而不是 SQL 线程延迟。

8. 参数配置不合理

  • 原因
    • 刷盘策略:如果从库的 innodb_flush_log_at_trx_commitsync_binlog 都设置为 1(双1标准),每次事务回放都需要强制刷盘,极大地消耗磁盘 IO。
    • 未使用多线程复制:MySQL 5.7 以上版本,如果没有正确开启并配置 slave_parallel_workers(MTS),将无法利用多核优势。

💡 如何排查和解决?

  1. 查看延迟情况
    在从库执行 SHOW SLAVE STATUS\G(或 MySQL 8.0 的 SHOW REPLICA STATUS\G)。

    • 查看 Seconds_Behind_Master(落后主库的秒数)。
    • 观察 Slave_IO_RunningSlave_SQL_Running 是否均为 Yes
    • 查看 Relay_Log_Space:如果该值很大,说明网络没问题(Binlog已经拉过来了),是 SQL 线程回放太慢。
  2. 定位具体原因

    • 使用 show processlist; 看从库 SQL 线程在干什么(是不是在等锁,或者在执行巨慢的语句)。
    • 检查近期是否有跑批任务(大事务)、DDL 操作。
    • 排查是否有无主键的表发生了更新。
  3. 常用优化手段

    • 开启多线程复制(MTS)。
    • 将从库的刷盘参数调低(如 innodb_flush_log_at_trx_commit=2, sync_binlog=0,注意这会牺牲从库宕机时的数据安全性来换取性能)。
    • 强制所有表必须有主键。
    • 大事务拆分成小事务执行。
    • 读写分离时,对实时性要求极高的读操作路由回主库。
00:00
00:00