mysql主从复制的工作流程是怎样的_mysql同步流程解析

6次阅读

主库通过dump Thread将row/mixed格式binlog实时推送给从库;从库由io_thread拉取写入relay log,sql_thread回放;gtid模式用全局事务id替代文件位点,提升切换与一致性;延迟主因sql线程卡在大事务、ddl或硬件瓶颈。

mysql主从复制的工作流程是怎样的_mysql同步流程解析

主库怎么把变更发给从库

主库不是实时推送数据,而是把所有写操作(INSERTUPDATEdelete)记录到本地的 binlog 文件里。这个过程由 dump thread 负责:当从库发起连接后,主库会为它单独起一个线程,持续读取 binlog 并发送给从库。

关键点:

  • binlog 格式必须是 ROWMIXEDSTATEMENT 在某些函数(如 NOW()UUID())下会导致主从不一致
  • 主库不会校验从库是否收到或执行成功,只管发;丢包或网络中断时,从库靠 IO_THREAD 自动重连并续传
  • 如果主库 binlog 被清理(expire_logs_days 到期或手动 PURGE BINLOGS),而从库还没来得及拉取,就会报错 Could not find first log file name in binary log index file

从库怎么接收和执行这些变更

从库有两个核心线程:IO_THREADSQL_THREADmysql 8.0.22+ 可启用 applier worker threads 并行回放)。

IO_THREAD 负责连接主库、拉取 binlog 内容,并写入本地的 relay log 文件;SQL_THREAD 则读取 relay log,解析成具体语句并执行。

常见问题:

  • Seconds_Behind_Master 显示为 NULL,通常是 IO_THREAD 没连上主库(检查 SHOW SLAVE STATUSG 中的 Slave_IO_Running 和网络连通性)
  • SQL_THREAD 报错停住(如主键冲突、表不存在),需要人工干预:SET GLOBAL sql_slave_skip_counter = 1(仅限 STATEMENT 格式)或用 gtid_next 跳过(推荐 GTID 模式)
  • 单线程回放容易成为瓶颈,尤其在大事务或高并发写场景下;开启多线程需设置 slave_parallel_type = LOGICAL_CLOCKslave_parallel_workers > 0

GTID 模式下同步逻辑有什么不同

启用 gtid_mode = ON 后,每个事务自带唯一标识 server_uuid:transaction_id,不再依赖 binlog 文件名和位置。

优势明显:

  • 从库切换主库时无需计算 CHANGE MASTER TO ... MASTER_LOG_FILE/MASTER_LOG_POS,直接 CHANGE MASTER TO MASTER_AUTO_POSITION = 1
  • 自动避免重复执行:从库会跳过自己已执行过的 GTID
  • 主库故障后,能快速选出最完整的新主库(看 select @@global.gtid_executed 最大值)

但要注意:

  • 所有节点必须统一开启 GTID,不能混用 FILE/POSAUTO_POSITION
  • 不支持 CREATE table ... SELECT 这类隐式事务语句(会报错 Statement violates GTID consistency
  • 使用 mysqldump 备份恢复时,必须加 --set-gtid-purged=ON,否则从库无法启动复制

为什么同步延迟经常忽高忽低

延迟不是线性增长的,典型表现为:平时 Seconds_Behind_Master = 0,突然涨到几百秒,又快速回落。这通常不是网络问题,而是执行层卡点。

根本原因集中在 SQL_THREAD 回放阶段:

  • 大事务(如单个 UPDATE 影响百万行)会阻塞整个 SQL 线程,后续所有 relay log 都得排队
  • 从库 innodb_flush_log_at_trx_commit = 1 + sync_binlog = 1 会显著拖慢回放速度(主库可以关,但从库一般不敢关)
  • 从库硬件比主库弱(尤其是磁盘 I/O),或者被其他查询大量占用 CPU/内存,导致回放跟不上
  • DDL 操作(如 ALTER TABLE)在从库执行时间远超主库,期间完全阻塞复制流

查延迟真实来源,别只盯 Seconds_Behind_Master:用 pt-heartbeat 打点测端到端延迟,或看 SHOW PROCESSLISTSQL_THREAD 是否长期处于 Waiting for table metadata lockUpdating 状态。

text=ZqhQzanResources