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

主库怎么把变更发给从库
主库不是实时推送数据,而是把所有写操作(INSERT、UPDATE、DELETE)记录到本地的 binlog 文件里。这个过程由 dump thread 负责:当从库发起连接后,主库会为它单独起一个线程,持续读取 binlog 并发送给从库。
关键点:
-
binlog格式必须是ROW或MIXED,STATEMENT在某些函数(如NOW()、UUID())下会导致主从不一致 - 主库不会校验从库是否收到或执行成功,只管发;丢包或网络中断时,从库靠
IO_THREAD自动重连并续传 - 如果主库
binlog被清理(expire_logs_days到期或手动PURGE BINLOGS),而从库还没来得及拉取,就会报错Could not find first log file name in binary log index file
从库怎么接收和执行这些变更
从库有两个核心线程:IO_THREAD 和 SQL_THREAD(MySQL 8.0.22+ 可启用 applier worker threads 并行回放)。
IO_THREAD 负责连接主库、拉取 binlog 内容,并写入本地的 relay log 文件;SQL_THREAD 则读取 relay log,解析成具体语句并执行。
常见问题:
-
Seconds_Behind_Master显示为NULL,通常是IO_THREAD没连上主库(检查SHOW SLAVE STATUS\G中的Slave_IO_Running和网络连通性) -
SQL_THREAD报错停住(如主键冲突、表不存在),需要人工干预:SET GLOBAL sql_slave_skip_counter = 1(仅限STATEMENT格式)或用gtid_next跳过(推荐 GTID 模式) - 单线程回放容易成为瓶颈,尤其在大事务或高并发写场景下;开启多线程需设置
slave_parallel_type = LOGICAL_CLOCK和slave_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/POS和AUTO_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 PROCESSLIST 中 SQL_THREAD 是否长期处于 Waiting for table metadata lock 或 Updating 状态。










