MySQL双主复制写入不生效的根源是auto-increment配置不当和server-id冲突,需配对设置increment/offset、确保server-id唯一、启用log-slave-updates,并严格遵循GTID一致性要求。

MySQL双主复制配置后写入不生效?检查auto-increment偏移和server-id
双主架构下最常见现象是:A库插入成功,B库查不到;或者两边都插入但主键冲突报错Duplicate entry '1' for key 'PRIMARY'。根本原因是两个实例的auto_increment_increment和auto_increment_offset没配对,导致自增ID重复。
实操建议:
- 主库A设
auto_increment_increment = 2、auto_increment_offset = 1;主库B设auto_increment_increment = 2、auto_increment_offset = 2 -
server-id必须全局唯一,且不能为0(常见坑:Docker容器重启后IP变,server-id硬编码成1,两节点撞了) - 启用
log-slave-updates——否则从库无法再作为主库转发binlog,双主链路就断了 - 不要用
mysqldump --single-transaction直接导出导入做初始化,它不保证GTID一致性;应先SET GLOBAL gtid_purged = 'xxx'再导入
GTID模式下主从同步中断,show slave status显示Retrieved_Gtid_Set为空?
这说明从库根本没拉到任何binlog事件,不是数据差异问题,而是复制通道没建立起来。典型诱因是主库没开GTID,或从库执行了CHANGE MASTER TO ... MASTER_AUTO_POSITION = 0却没指定MASTER_LOG_FILE和MASTER_LOG_POS。
实操建议:
- 主从两端都确认
gtid_mode = ON且enforce_gtid_consistency = ON,缺一不可 - 从库执行
CHANGE MASTER TO时,必须带MASTER_AUTO_POSITION = 1,不能混用文件+位置模式 - 如果主库已开启GTID但从库之前是传统模式,需先
RESET SLAVE ALL清空旧状态,再重配 - 检查主库
SHOW MASTER STATUS输出的Executed_Gtid_Set是否非空;若为空,说明主库压根没产生GTID事务(比如开了GTID但没执行过DDL/DML)
异地多活场景下,应用层写入两个主库,怎么避免更新丢失?
双主不等于双写自由。MySQL本身不解决跨库并发更新冲突,比如两地用户同时改同一条订单状态,最终只会保留其中一个结果,另一个被覆盖。
实操建议:
- 业务表必须有
updated_at时间戳字段,并在UPDATE语句里加上WHERE updated_at = ?条件,靠应用层重试+版本校验兜底 - 禁止对同一行做无条件UPDATE(如
UPDATE user SET balance = balance + 100),这类操作在双主下必然导致数据倾斜 - 敏感业务(如支付、库存)强制路由到单一中心主库,异地只读;所谓“多活”是按业务域切分,不是所有表都双写
- 监控
Seconds_Behind_Master的同时,必须加一层应用级心跳表(如heartbeat表每秒写一次当前时间),否则网络分区时从库假活
MySQL 5.7升级8.0后双主复制报错The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs
这是GTID模式下最棘手的错误之一,本质是主库binlog被清理得太狠,从库需要的GTID区间已经不在gtid_purged里了。
实操建议:
- 升级前主库执行
SELECT @@gtid_purged并记录;从库升级后,用SET GLOBAL gtid_purged = '记录值'手动补全 - 升级期间暂停写入,或确保主库
expire_logs_days足够大(建议≥7),避免binlog被自动删除 - 8.0默认
enforce_gtid_consistency更严格,建表语句含CREATE TEMPORARY TABLE会直接报错,需提前清理 - 别信“只要主从GTID一致就能跳过”——
gtid_executed和gtid_purged是两个集合,后者才是从库找日志的起点
异地多活真正的复杂点不在MySQL配置,而在于你能否清晰定义每一行数据的“属地”。一旦出现跨地域修改同一行的需求,数据库层已经救不了了——得回到业务逻辑里划边界。










