什么是互为主从?

互为主从是 MySQL 主从复制架构的一种高级形式。在标准的主从复制中,一个主库(Master)处理所有写操作,并将数据变更同步到一个或多个从库(Slave)。而在互为主从架构中,两个 MySQL 实例互为对方的主库和从库。

  1. 节点A:既是节点B的主库,也是节点B的从库。

  2. 节点B:既是节点A的主库,也是节点A的从库。

这样一来,两个节点都可以独立地接受客户端的读写请求,并且它们之间的数据变更会相互同步

互为主从的限制

“互为主从”(双主架构)的核心限制是:不能同时在两个数据库上随意写入,否则必然产生冲突。它本质上是两个单向的主从复制关系

主要限制体现在:

  1. 数据冲突:两边同时修改同一行数据时,系统无法自动判断以哪个为准。
    例如: 在A库将库存改为10,同时在B库改为5,结果无法确定。

  2. 自增ID冲突:两边各自生成新数据时,可能会产生相同的自增ID,导致同步失败。
    解决方案: 预先设置A库生成奇数ID,B库生成偶数ID。

  3. 数据延迟:写入一个数据库后,在另一个库不会立刻查到,只能保证“最终一致”。

因此,实用的做法是:
虽然两个库理论上都能写,但必须在业务层面做划分。比如规定:用户相关的写入只走A库,订单相关的写入只走B库。从根源上避免同时对同一类数据进行写操作。

互为主从的核心原理

互为主从的本质是两个单向的主从复制通道(A -> B 和 B -> A)的组合。每个节点都需要开启二进制日志(binlog),并配置一个用于复制的用户。

配置互为主从

一、环境准备

准备两台服务器:

Master-A: IP 地址为 192.168.4.51

Master-B: IP 地址为 192.168.4.52

MySQL 版本:5.7 或以上(配置在 8.0 中也基本通用)
注意!两台服务器都需要关闭selinux与防火墙,否则重启mysqld服务可能会报错以及后面指定主服务器后slave status的Slave_IO_Running不能成功运行

二、第一部分:基础配置(Master-A 和 Master-B)

这一步在两台服务器上几乎完全相同。

1.安装 MySQL

确保两台服务器上都已安装相同版本的 MySQL。如果未安装,请使用系统包管理器安装。

2.编辑 MySQL 配置文件

修改配置文件 /etc/my.cnf并重启 MySQL

Master-A 的配置文件 (/etc/my.cnf)

在[mysqld]添加四行内容:

server_id=51
log_bin=master51         #记录操作日志
# 自增主键的配置,防止双主环境下ID冲突
# 自增偏移,A从1开始,每次加2 (1, 3, 5, ...)
auto_increment_increment = 2
auto_increment_offset = 1

Master-B 的配置文件 (/etc/my.cnf)

在[mysqld]添加两行内容:

server_id=51
log_bin=master51         #记录操作日志
# 自增主键的配置,B从2开始,每次加2 (2, 4, 6, ...)
auto_increment_increment = 2
auto_increment_offset = 2

3.用户授权

Master-A 和Master-B都执行

grant replication slave on *.* to repluser@"%" identified by "123qqq...A";

4.指定主服务器信息

Master-A

mysql> show master status;
+-----------------+----------+--------------+------------------+-------------------+
| File            | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+-------------------+
| master51.000002 |      738 |              |                  |                   |
+-----------------+----------+--------------+------------------+-------------------+

mysql> change master to master_host="192.168.4.52", master_user="repluser", master_password="123qqq...A", master_log_file="master52.000005", master_log_pos=446;
Query OK, 0 rows affected, 2 warnings (0.03 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

Master-B

mysql> show master status;
+-----------------+----------+--------------+------------------+-------------------+
| File            | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+-------------------+
| master52.000005 |      446 |              |                  |                   |
+-----------------+----------+--------------+------------------+-------------------+
mysql> change master to master_host="192.168.4.51", master_user="repluser", master_password="123qqq...A", master_log_file="master51.000002", master_log_pos=738;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

5.检查复制状态

在两台服务器上都执行:

mysql> show slave status\G;

查看关键字段:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_IO_Error: (应该为空)
Last_SQL_Error: (应该为空)

6.测试配置

Master-A 上执行插入数据

mysql> create database test_simple;
Query OK, 1 row affected (0.01 sec)

mysql> create table test_simple.data_log (id int primary key, message varchar(100), created_at timestamp);
Query OK, 0 rows affected (0.02 sec)

mysql> insert into data_log values (1, 'data from master-a', now());
ERROR 1046 (3D000): No database selected
mysql> insert into test_simple.data_log values (1, 'data from master-a', now());
Query OK, 1 row affected (0.02 sec)

Master-B 上检查

mysql> select * from test_simple.data_log;
+----+--------------------+---------------------+
| id | message            | created_at          |
+----+--------------------+---------------------+
|  1 | data from master-a | 2025-10-19 08:29:44 |
+----+--------------------+---------------------+
1 row in set (0.00 sec)

Master-B 上执行插入数据

mysql> insert into test_simple.data_log values (2, 'data from master-b', now());
Query OK, 1 row affected (0.00 sec)

Master-A 上检查

mysql> select * from test_simple.data_log;
+----+--------------------+---------------------+
| id | message            | created_at          |
+----+--------------------+---------------------+
|  1 | data from master-a | 2025-10-19 08:29:44 |
|  2 | data from master-b | 2025-10-19 08:32:22 |
+----+--------------------+---------------------+
2 rows in set (0.00 sec)

7.故障恢复场景

如果复制因为错误停止,需要重新获取位置:

1.查看错误信息:

show slave status\G

– 查看 Last_SQL_Error 和 Last_IO_Error

2.重新获取主库位置:
在出问题的主库上执行:

show master status;

3.重新配置从库:
在从库上执行:

stop slave;

change master to master_host="192.168.4.51", master_user="repluser", master_password="123qqq...A", master_log_file="master51.000002", master_log_pos=738;
-- 使用目前的的File
-- 目前的Position

start slave;
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐