MySQL互为主从(双主模型)是指两台数据库服务器彼此配置为对方的主库和从库,任意一端执行的数据变更都会通过二进制日志复制到对端。这种架构在不依赖中间件的情况下,提供了双向写入能力与本地高可用基础,常用于同城双活或避免单点写入故障的场景。
一、双主模型的核心原理
在标准的MySQL主从复制中,一台服务器充当主库(Master),另一台为从库(Slave),数据单向流动。互为主从则打破了这种单向性:服务器A把自身产生的二进制日志(binlog)发送给服务器B重放,同时服务器B也把自身的binlog发送给服务器A重放。两者都开启了log-bin与log-slave-updates,从而形成一个闭合的复制环。
要避免复制环引发无限循环,MySQL依赖server-id机制。每个事件都带有产生它的server-id,从库应用中继日志时若发现事件server-id与自身相同则直接丢弃。此外,双主最棘手的问题是自增主键冲突,因为两端都可能插入新行。通过错开auto_increment_offset与auto_increment_increment,可以让两台机器生成不重叠的ID序列,从根源上消除冲突。
二、基础环境准备与参数配置
假设我们有两台服务器:节点一IP为192.168.0.1,节点二IP为192.168.0.2,均使用MySQL 8.0。第一步是修改配置文件并重启服务。下面给出节点一的典型配置片段,节点二仅需把server-id和IP互换即可。
[mysqld] server-id=1 log-bin=mysql-bin binlog-format=ROW relay-log=relay-bin log-slave-updates=1 auto_increment_increment=2 auto_increment_offset=1 bind-address=0.0.0.0
节点二配置中将server-id设为2,auto_increment_offset设为2,其余保持一致。auto_increment_increment=2表示ID步长为2,offset分别为1和2,因此节点一生成1、3、5……,节点二生成2、4、6……,永远不会撞车。配置完成后需确认两台机器的防火墙放通3306端口,并且双方能用命令行互相访问。
创建专门用于复制的账号非常关键,不要复用root。在两台节点分别执行如下语句,注意用户名和密码应一致以便对端连接。
CREATE USER 'repl'@'192.168.0.%' IDENTIFIED BY 'ReplPass123'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.%'; FLUSH PRIVILEGES;
三、建立互为主从的复制链路
先在节点一查看自身binlog状态,记录File与Position,随后到节点二配置指向节点一的主库信息并启动Slave。反之再操作一次,使节点一指向节点二。以下为节点二连接节点一的命令示例:
CHANGE MASTER TO MASTER_HOST='192.168.0.1', MASTER_USER='repl', MASTER_PASSWORD='ReplPass123', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=157; START SLAVE;
在节点一上则把MASTER_HOST改为192.168.0.2,并填入节点二对应的日志坐标。执行完毕后,使用SHOW SLAVE STATUSG检查Slave_IO_Running与Slave_SQL_Running是否均为Yes。若某端显示Connecting,通常是网络不通或账号权限问题;若SQL线程报错,多为初始数据不一致或DDL冲突。
为验证双向同步,可在节点一新建库表并插入数据,观察节点二是否出现相同记录;再于节点二插入一条,看节点一是否同步。只有两个方向都通,双主模型才算搭建成功。此时任意一端宕机,另一端仍可独立承担读写。
四、避免常见误区与数据冲突
虽然双主支持双向写,但生产环境常建议“单点写、双节点热备”。若真要双写,必须确保相同表不会在两台机器被并发修改同一行,否则会出现数据分歧且复制报错。一种做法是按业务维度分库,节点一负责订单库写入,节点二负责用户库写入,互不交叉。
另一个误区是忽略auto_increment配置。如果忘记设置offset,两台机器都从1开始自增,第一次双向插入就会主键重复,SQL线程随即停止。此外,使用statement格式的binlog在含UUID或时间函数的场景下可能造成两端执行结果不同,因此推荐binlog-format=ROW,以行镜像保证一致性。
五、结合高可用组件的实操思路
纯双主只是数据互通,客户端仍面临“该连哪台”的问题。引入keepalived可为两台机器提供一个虚拟IP(VIP),通过健康检测脚本定时探活MySQL,谁活谁挂VIP。以下为简单检测脚本逻辑:
#!/bin/bash if ! mysql -urepl -pReplPass123 -e "SELECT 1" >/dev/null 2>&1; then systemctl stop keepalived fi
将脚本配入keepalived的vrrp_script,主节点故障时VIP漂到备节点,应用无感知。需要注意的是,若原主节点恢复,不要自动抢回VIP导致脑裂,应设为非抢占模式或人工介入。双主加VIP构成了轻量级高可用,比单主模型切换更快,但不具备强一致多写,适合容忍短暂异步延迟的系统。
| 架构 | 写入方向 | 故障切换 | 复杂度 |
|---|---|---|---|
| 单主一从 | 单向 | 需手动或工具提升从库 | 低 |
| 互为主从(双主) | 双向 | VIP漂移即可 | 中 |
六、运维监控与日常维护
双主环境应持续监控Seconds_Behind_Master指标,若延迟持续增大,说明某端写入压力高或网络吞吐不足。可借助Prometheus配合mysqld_exporter采集复制状态,设置告警阈值。定期校验两端数据一致性也很有必要,可使用pt-table-checksum工具发现潜差异。
版本升级或参数调整时,优先在备用节点操作,确认复制正常后再切VIP,降低对业务影响。备份策略上,两端都可做物理备份,但因数据同源,只需保留一份全量加binlog即可满足恢复需求。厘清这些细节后,MySQL互为主从模型便能稳定支撑中小规模的高可用数据库服务。