MySQL主从同步是基于binlog的异步/半同步复制机制,存在延迟与不一致风险;需配置ROW格式、监控IO/SQL线程状态、合理使用GTID及半同步以提升可靠性。

MySQL 主从同步不是自动“实时一致”的管道,而是一套基于二进制日志(binlog)的异步/半同步复制机制;主库写入后,从库需拉取、重放日志才能追上——这意味着延迟、不一致窗口和潜在的数据断裂风险。
主从复制依赖 binlog 格式与执行模式
主库必须开启 binlog,且格式直接影响从库重放行为和一致性保障能力:
-
STATEMENT:记录 SQL 语句本身;在含NOW()、UUID()、用户变量等非确定性函数时,从库执行结果可能与主库不同 -
ROW:记录每行数据变更前后的镜像;安全但体积大,尤其批量更新时binlog膨胀明显 -
MIXED:默认混合模式,对非确定性语句自动切到ROW;但无法完全规避判断盲区,生产环境建议显式设为ROW
确认当前格式:
SHOW VARIABLES LIKE 'binlog_format';修改需在主库配置文件中设置
binlog_format = ROW 并重启(或动态生效,取决于 MySQL 版本)。
从库 IO 线程与 SQL 线程分工明确,各自可能中断
复制由两个独立线程协作完成,故障点也分离:
-
IO_THREAD:连接主库,拉取binlog事件并写入本地relay log;中断常见于网络超时、主库权限不足(如复制用户无REPLICATION SLAVE权限)、主库binlog被清理(expire_logs_days过小) -
SQL_THREAD:读取relay log,逐条重放;中断多因语句冲突(如从库有同名表但结构不同)、DDL 与 DML 并发导致锁等待、或遇到STOP SLAVE后未手动恢复
检查状态用:
SHOW SLAVE STATUS\G重点看
Slave_IO_Running 和 Slave_SQL_Running 是否均为 Yes,以及 Seconds_Behind_Master 是否持续增长。
GTID 模式能简化故障恢复,但要求全集群统一启用
传统基于文件名+位置(File/Position)的复制,在主库切换或从库异常后需要人工计算偏移量;GTID(Global Transaction Identifier)为每个事务分配唯一 ID,使从库可自动定位并跳过已执行事务:
- 启用前需确保所有节点
gtid_mode = ON且enforce_gtid_consistency = ON - 从库执行
CHANGE MASTER TO ... GTID_SET = ...时,若GTID_EXECUTED不匹配,会报错ERROR 1236 (HY000),此时需用SET GLOBAL gtid_purged = '...'手动补全(仅当确认缺失事务已丢失时才可操作) - GTID 下
RESET SLAVE会清空gtid_executed,务必搭配RESET SLAVE ALL避免后续启动失败
查看当前 GTID 状态:
SELECT @@global.gtid_mode, @@global.gtid_executed;
半同步复制不能消除延迟,只约束主库提交行为
启用 rpl_semi_sync_master_enabled 后,主库 COMMIT 将阻塞直到至少一个从库确认收到 binlog(而非执行完成),这能防止主库宕机后丢失已提交事务,但:
- 仍不保证从库已重放,
Seconds_Behind_Master可能很大 - 若所有半同步从库失联,主库会自动退化为异步模式(由
rpl_semi_sync_master_timeout控制超时时间) - 性能敏感场景下,超时值设太小易频繁降级,设太大则拖慢主库响应
启用后验证:
SELECT plugin_name, plugin_status FROM information_schema.plugins WHERE plugin_name LIKE '%semi%';
真正难处理的是主库崩溃后如何选新主——GTID + MHA 或 Orchestrator 可自动完成,但切换过程中的脑裂、从库数据不完整、应用连接未及时刷新等问题,远比配置复制参数更消耗运维精力。










