MySQL双主复制本身不能实现自动高可用,因其仅提供双向数据同步通道,缺乏故障感知、流量自动路由和写冲突消解能力;业务直连单节点时宕机即断连,必须配合Keepalived VIP、ProxySQL等中间件才能实现无感切换与真正高可用。

MySQL双主(Master-Master)能实现高可用和负载均衡,但必须配合中间件或VIP机制,否则业务层无法自动切换,写冲突风险极高。
为什么不能只靠双主复制就“自动高可用”
MySQL原生双主只是双向复制通道,不提供故障感知、流量路由或写冲突消解能力。业务应用直连某台MySQL时,若该节点宕机,连接会断开,不会自动跳转到另一台——这跟单主没区别。
常见错误现象包括:
- 应用配置了
jdbc:mysql://192.168.10.101:3306/db,主机1挂了,连接超时,业务报错 - 两个节点同时插入无显式主键的记录,因
auto_increment_offset和auto_increment_increment配置失误,导致主键冲突,复制中断 - 网络抖动后,
Seconds_Behind_Master显示为NULL或负值,但Slave_IO_Running和Slave_SQL_Running仍为Yes,实际已不同步
必须配置的MySQL核心参数(两节点差异化设置)
双主不是“配两遍一样的配置”,关键参数必须错开,否则自增ID、GTID或日志位置会打架。
节点1(IP 192.168.10.101)的 my.cnf 中需包含:
[mysqld] server-id = 1 log-bin = mysql-bin binlog-format = ROW sync_binlog = 1 auto_increment_increment = 2 auto_increment_offset = 1
节点2(IP 192.168.10.102)则必须是:
[mysqld] server-id = 2 log-bin = mysql-bin binlog-format = ROW sync_binlog = 1 auto_increment_increment = 2 auto_increment_offset = 2
说明:
-
server-id全局唯一,不可重复 -
auto_increment_increment和auto_increment_offset组合保证双节点生成的自增ID不重叠(如节点1出1,3,5…,节点2出2,4,6…) -
binlog-format = ROW是强推荐项,STATEMENT模式在函数、时间戳等场景下极易导致主从不一致
如何让业务真正“无感切换”:必须引入VIP或代理层
裸双主对应用完全透明是不可能的。真实生产中,必须加一层访问抽象:
- 用
Keepalived+ 虚拟IP(VIP),例如192.168.10.100,绑定在当前健康的MySQL节点上;应用只连这个VIP,故障时VIP秒级漂移到另一节点 - 用
HAProxy做TCP层负载均衡,配置健康检查(如检测/health?check=mysql端点),自动剔除异常节点;读写请求可统一走HAProxy,由它转发 - 用
ProxySQL或MySQL Router实现读写分离:写强制发往主组(hostgroup 10),读按权重分发到两个主节点(hostgroup 20)
注意:MySQL Router 默认不支持双主写负载均衡,需配合 --conf-use-gr 和 GTID 模式,并手动定义 hostgroup 写组为“多主可写”;而 ProxySQL 的 mysql_replication_hostgroups 表需明确标记两个节点都属于 writer_hostgroup。
最容易被忽略的三个实操细节
很多团队卡在最后一步,不是配不通,而是没守住边界:
- 防火墙必须放行两节点之间的
3306端口,且replication_user的授权 Host 不能写'%'(存在DNS反查延迟),建议用具体IP或网段,如'192.168.10.%' - 双主间不要启用
read_only=ON全局设置,否则会导致对方的写入被拒绝;如需防护,仅对非业务账号设REPLICATION CLIENT权限,而非SUPER - 所有表必须有主键或非空唯一键,否则
ROW格式复制在更新/删除时可能匹配多行或零行,造成数据逻辑不一致,且难以定位
双主不是“配完就稳”,它把复杂性从数据库层推到了运维层和架构层——冲突处理、脑裂判断、切换验证,每一步都要有对应手段,否则高可用会变成高风险。


















