mysql主从复制默认为异步模式,存在数据丢失风险;要保障可靠性与近实时性,必须启用row格式、gtid及半同步插件,并严格配置sync-binlog=1、innodb-flush-log-at-trx-commit=1、relay-log与read-only等关键参数。

MySQL主从复制默认就是异步的,所谓“实时”只是毫秒级延迟,并非强一致;要接近实时且可靠,必须用 ROW 格式 + GTID + 半同步插件,否则容易丢数据或主从不一致。
主库必须启用 binlog 并设为 ROW 格式
STATEMENT 模式在 NOW()、UUID()、自增主键等场景下会主从不一致,ROW 是唯一安全选择。配置项不能只写 binlog-format=ROW,还要加关键保障:
-
binlog-row-image=FULL:确保所有列变更都被记录(尤其 UPDATE 时) -
sync-binlog=1:每次事务提交都刷盘,避免主机宕机丢失 binlog -
innodb-flush-log-at-trx-commit=1:InnoDB 日志也强制落盘,和 binlog 保持一致 - 别漏掉
gtid-mode=ON和enforce-gtid-consistency=ON,否则后续无法开启 GTID 复制
从库必须开 relay log 且设为只读
relay log 不是可选——它是复制的中间缓冲,SQL 线程靠它重放。常见错误是只配了 server-id 却没开 relay-log,导致 START SLAVE 报错 “Could not initialize master info structure”。正确做法:
- 显式设置
relay-log=mysql-relay-bin(路径需有写权限) - 加上
read-only=ON:防止应用误写从库造成主从冲突 - 若用 MySQL 8.0.12+,建议加
super-read-only=ON,连 root 都不能绕过 - 别设
skip-slave-start=1,否则重启后复制自动停止,得手动START SLAVE
CHANGE MASTER TO 必须用 GTID 而非 FILE/POS
手动指定 MASTER_LOG_FILE 和 MASTER_LOG_POS 是旧方式,极易出错:主库 rotate binlog 后位置失效,从库报 Could not find first log file name in binary log index file。GTID 自动定位,只要主从都开了 GTID,命令就极简:
CHANGE MASTER TO MASTER_HOST='192.168.1.10', MASTER_USER='repl', MASTER_PASSWORD='replpass', MASTER_PORT=3306, GET_MASTER_PUBLIC_KEY=1, MASTER_AUTO_POSITION=1;
注意:MASTER_AUTO_POSITION=1 是开关,不是可选参数;GET_MASTER_PUBLIC_KEY=1 是 MySQL 8.0 默认要求(用于 RSA 密钥交换)。
验证复制是否真正在跑,别只看 Slave_IO_Running
SHOW SLAVE STATUS\G 输出里两个线程状态都得是 Yes,但更关键的是:
-
Seconds_Behind_Master: 0≠ 实时——它可能卡在锁等待、大事务回放中,实际延迟已累积 - 检查
Retrieved_Gtid_Set和Executed_Gtid_Set是否相等,不等说明 SQL 线程没追上 - 查
Slave_SQL_Running_State:如果是Waiting for an event from Coordinator,说明并行复制正常;若是Reading event from the relay log,大概率是单线程慢 - 线上务必开
slave_parallel_workers=4(至少等于 CPU 核数一半),否则大表 DDL 或批量 INSERT 会让从库越追越远
最易被忽略的一点:主从时间不同步会导致 GTID 冲突或 binlog 解析异常,所有节点必须跑 NTP 服务校准时间——哪怕差 2 秒,都可能让 mysqlbinlog 解析失败或复制中断。











