1. 什么是多源复制
MySQL 5.7发布后,在复制方面有了很大的改进和提升。比如开始支持多源复制(multi-source)以及真正的支持多线程复制了。多源复制可以使用基于二进制日志的复制或者基于事务的复制。下面我们说一说如何配置基于二进制日志的多源复制。
首先,我们要清楚几种常见的复制模式:
1)一主一从
2)一主多从
3)级联复制
4)multi-master
MySQL 5.7 之前只能支持一主一从,一主多从或者多主多从的复制。如果想实现多主一从的复制 只能使用mariadb,但是mariadb又与官方的mysql版本不兼容。
MySQL 5.7 开始支持了多主一从的复制方式也就是多源复制。MySQL 5.7 版本相比之前的版本,无论是功能还是性能还是安全等方面都已经有了不少的提升。
首先我们要清楚multi-master OR multi-source 复制不是一样的。multi-master复制通常是环形的复制,可以在任意的主机上将数据复制给其他的主机。如图:

multi-source 是不同的。简单的说,多源复制就是将多个主库同步到一个从库,从而增加从的利用率,节省了机器。如图:

2. 多源复制的使用场景
数据分析部门会需要各个业务部门的部分数据做数据分析,这个时候就可以使用到多源复制把各个主数据库的数据复制到统一的数据库中。
在从服务器进行数据的汇总,如果我们的主服务器进行了分库分表的操作,为了实现后期的一些数据的统计功能,往往要把数据汇总在一起在进行统计。
在从服务器对所有主服务器的数据进行备份,在MySQL 5.7之前每个主服务器都需要一台从服务器,这样很容易造成资源的浪费,同时也加大了DBA的维护成本,但MySQL 5.7引入的多源复制,可以把多个主服务器的数据同步到一台从服务器进行备份。
3. 多源复制的必要条件
不管是使用基于二进制日志的复制或者基于事务的复制,要开启多源复制功能必须要在从库上设置master-info-repository AND relay-log-info-repository 这两个参数。
这两个参数是用来存储同步信息的,可以设置的值为FILE和TABLE,默认是FILE。比如master-info就保存在master.info文件中,relay-log-info保存在relay-log.inf文件中服务器如果意外关闭,正确的relay-log-info没有来的及更新带relay-log.info文件,这样就会造成数据的丢失。
为了数据更加安全,通常设置为TABLE。这些表都是innodb类型的,支持事务。相对文件存储安全得多。在MySQL库下可以看到这两个表的信息,分别是mysql.slave_master_info AND mysql.slave_relay_log_info
这两个参数也是可以动态调整的。
bash
SET GLOBAL master_info_repository = 'TABLE';
SET GLOBAL relay_log_info_repository = 'TABLE';
如果要启用enhanced multi-threaded slave(多线程复制),可以设置一下参数
bash
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=8
relay_log_recovery=ON
如果SLAVE已经为开启状态,那么需要首先关闭SLAVE(stop slave;)
4. 配置主库 (Master A & Master B)
注意:主库配置的server-id需要唯一
4.1 Master A (假设 IP: 192.168.1.100, 端口: 3306)
1 )找到MySQL配置文件
MySQL在Windows环境下的配置文件默认是 my.ini,位置通常在:
- 安装目录下(如:D:\Program Files\MySQL\MySQL Server 8.0\my.ini)
- 若未找到,可通过"服务"查看MySQL服务的可执行路径,找到对应配置文件(右键MySQL服务→属性→可执行文件路径)。
bash
[mysqld]
server-id = 10
log-bin = mysql-bin
binlog-format = ROW
binlog-row-image = FULL
4.2 Master B (假设 IP: 192.168.1.120, 端口: 3306)
1 )找到MySQL配置文件
MySQL在Windows环境下的配置文件默认是 my.ini,位置通常在:
- 安装目录下(如:D:\Program Files\MySQL\MySQL Server 8.0\my.ini)
- 若未找到,可通过"服务"查看MySQL服务的可执行路径,找到对应配置文件(右键MySQL服务→属性→可执行文件路径)。
bash
[mysqld]
server-id = 20
log-bin = mysql-bin
binlog-format = ROW
binlog-row-image = FULL
4.3 重启主库服务
控制面板→管理工具→服务→找到"MySQL"→右键"重启"。
注意:若重启失败,大概率是my.ini配置有误(如语法错误、路径错误),需检查配置文件并修正后重新尝试。
4.4 创建复制用户
在 Master A 和 Master B 分别执行创建授权账号,打开Navicat输入如下查询语句
bash
-- Master A
CREATE USER 'test_db'@'%' IDENTIFIED BY 'test_db123456';
GRANT REPLICATION SLAVE ON *.* TO 'test_db'@'%';
FLUSH PRIVILEGES;
-- Master B
CREATE USER 'test_db'@'%' IDENTIFIED BY 'test_db123456';
GRANT REPLICATION SLAVE ON *.* TO 'test_db'@'%';
FLUSH PRIVILEGES;
5. 配置从库 (Slave)
5.1 修改从库my.ini配置
同样找到从库的my.ini文件,在[mysqld]节点下添加/修改以下配置
bash
[mysqld]
server-id = 30
master-info-repository = TABLE # 必须!使用表存储主库信息
relay-log-info-repository = TABLE # 必须!
# 从库可选优化参数
read-only = 1 # 只读(超级用户除外)
log-bin = mysql-bin # 级联复制需要
log-slave-updates = 1 # 将从库变更写入binlog(级联场景)
# 只同步 test_db库(白名单,推荐)
replicate-do-db = test_db # 多个库写多行
5.2 重启从库服务
同主库重启方式,确保配置生效。
5.3 从库配置多源复制通道
打开Navicat输入如下语句
bash
-- 连接到 Slave
-- 配置 Master A 的通道 (命名为 master_a)
CHANGE MASTER TO
MASTER_HOST='192.168.1.100', # 主库IP地址
MASTER_PORT=3306, # 主库MySQL端口
MASTER_USER='test_db', # 主库创建的同步账号
MASTER_PASSWORD='test_db123456', # 同步账号密码
MASTER_LOG_FILE='mysql-bin.000002', # 主库SHOW MASTER STATUS输出的File值
MASTER_LOG_POS=154 # 主库SHOW MASTER STATUS输出的Position值
FOR CHANNEL 'master_a';
-- 配置 Master B 的通道 (命名为 master_b)
CHANGE MASTER TO
MASTER_HOST='192.168.1.120',
MASTER_PORT=3306,
MASTER_USER='test_db',
MASTER_PASSWORD='test_db123456',
MASTER_LOG_FILE='mysql-bin.000002',
MASTER_LOG_POS=154
FOR CHANNEL 'master_b';
-- 启动所有通道
START SLAVE FOR CHANNEL 'master_a';
START SLAVE FOR CHANNEL 'master_b';
若需要单独启动或停止某个同步通道,可使用如下命令:
start slave for channel 'master_a'; //启动名称为master_a的同步通道
stop slave for channel 'master_a'; //停止名称为master_a的同步通道
5.4 验证多源复制状态
打开Navicat输入如下查询语句
bash
-- 查看所有通道状态
SHOW SLAVE STATUS FOR CHANNEL 'master_a';
SHOW SLAVE STATUS FOR CHANNEL 'master_b';
只有【Slave_IO_Running】和【Slave_SQL_Running】都是Yes,则同步是正常的。
6. 相关操作
bash
#查看单个channel的状态
show slave status for channel 'master_a';
#停止单个channel的同步
stop slave for channel 'master_a';
#开启单个channel的同步
start slave for channel 'master_a';
#重置(删除)单个channel
reset slave all for channel 'master_a';
#查看所有channel
show slave status;
#停止所有channel
stop slave;
#开启所有channel
start slave;
7.跳过一个channel的报错
处理方法:先停止所有的channel,再执行 sql_slave_skip_counter,接着开启报错的channel,最后开启所有的channel。
bash
-- 步骤1:停止所有通道(确保完全停止)
STOP SLAVE;
-- 步骤2:设置默认通道(关键!)
SET @@default_master_connection = 'master_a'; -- MariaDB语法
-- 步骤3:设置跳过计数器
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
-- 步骤4:只启动指定通道(必须带FOR CHANNEL!)
START SLAVE FOR CHANNEL 'master_a';
-- 步骤5:验证并清零
SHOW GLOBAL VARIABLES LIKE 'sql_slave_skip_counter';
-- 确认自动归零后,再启动其他通道
START SLAVE FOR CHANNEL '其他通道';

8. 从库查看具体错误信息
bash
# 1. 从SHOW SLAVE STATUS获取关键信息
# Relay_Log_File: mysqld-relay-bin.005201
# Relay_Log_Pos: 256529594
# Exec_Master_Log_Pos: 256529431
# 2. 解析relay log查看失败语句(在从库执行)
mysqlbinlog --no-defaults -vv --base64-output=decode-rows --start-position=256529431 --stop-position=256529594 ../data/mysqld-relay-bin.000002 -r D:/output.sql
# 输出示例(Row格式解析后):### INSERT INTO `db`.`table`### SET### @1=123 /* INT meta=0 nullable=0 is_null=0 */### @2='conflict_value' /* VARSTRING(100) meta=100 nullable=1 is_null=0 */### @3='2024-01-15 10:30:00' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
关键参数:
- -vv:显示详细字段值(@1, @2对应表的第1,2列)
- --base64-output=decode-rows:将二进制行事件解码为可读SQL
- --start-position:从执行失败位置开始(Exec_Master_Log_Pos)
- --stop-position:到relay log当前位置(Relay_Log_Pos)