MySQL 主从复制是实现数据高可用、横向扩展、离线数据分析的核心技术,通过日志传输与重放机制实现多节点数据同步。本文将从复制核心原理入手,结合实操步骤讲解基础主从复制配置 、新增从库部署 、GTID 模式开启 及环形复制拓扑搭建,覆盖从单主单从到多节点环形同步的完整实操流程。
一、MySQL 复制核心原理与基础知识点
在进行实操配置前,先掌握 MySQL 复制的核心概念与关键知识点,是理解后续操作的基础。
1. 复制核心架构与模式
MySQL 默认采用异步复制模式 ,主库将数据变更写入二进制日志(Binary Log),从库通过两个核心线程实现数据同步:
- IO_THREAD :从库专属线程,与主库建立连接,拉取主库二进制日志并写入本地中继日志(Relay Log);
- SQL_THREAD:从库专属线程,读取本地中继日志,执行其中的 SQL 语句完成数据重放,实现主从数据一致。
2. 复制核心配置要求
- server-id :集群中每个 MySQL 节点必须配置唯一的服务器 ID,是复制拓扑中节点识别的核心标识,不可重复;
- 二进制日志 :主库必须开启
log-bin,用于记录所有数据变更操作,是复制的核心数据源; - 中继日志 :从库需开启
relay-log,用于暂存从主库拉取的二进制日志内容; - 复制用户 :主库需创建具备
REPLICATION SLAVE权限的专用用户,供从库拉取日志使用。
3. 复制关键特性与注意事项
- 主库可挂载的从库数量无理论限制,生产环境建议控制在 30 个以内,避免主库压力过大;
- 从库 MySQL 版本建议不低于主库,可向下兼容但不推荐,防止日志解析异常;
- 从库无需永久连接主库,断开后重新连接可从上次同步的日志位点继续同步;
- 基于语句的复制(SBR)存在局限性,非确定性函数(
RAND()/UUID()/NOW())会导致主从数据不一致,建议使用基于行的复制(RBR)。
4. 复制的典型应用场景
- 横向扩展:多从库分担读请求,实现读写分离,提升集群整体读性能;
- 高可用性:主库故障时,可将从库提升为主库,快速恢复业务,减少停机时间;
- 数据分析:从库承接离线统计、报表查询等操作,避免影响主库业务运行。
二、基础环境准备:MySQL 多实例配置
本次实操基于单服务器部署 MySQL 多实例(server1/server2/server3/server4,端口 3311-3314),模拟多节点复制集群,核心步骤为实例配置、服务管理与核心参数配置。
1. 停止默认 MySQL 服务
# 停止系统默认mysqld服务
systemctl stop mysqld
# 验证服务状态
systemctl status mysqld
2. 配置 MySQL 多实例基础参数
创建多实例配置文件,指定每个实例的端口、数据目录、套接字文件等基础参数:
cat > /Labs/multi.cnf << 'EOF'
[mysqld@server1]
user=mysql
socket=/mysql/server1.sock
port=3311
datadir=/mysql/data1
log-error=/mysql/server1.err
mysqlx=OFF
[mysqld@server2]
user=mysql
socket=/mysql/server2.sock
port=3312
datadir=/mysql/data2
log-error=/mysql/server2.err
mysqlx=OFF
[mysqld@server3]
user=mysql
socket=/mysql/server3.sock
port=3313
datadir=/mysql/data3
log-error=/mysql/server3.err
mysqlx=OFF
[mysqld@server4]
user=mysql
socket=/mysql/server4.sock
port=3314
datadir=/mysql/data4
log-error=/mysql/server4.err
mysqlx=OFF
EOF
3. 配置复制核心参数
编辑复制专用配置文件/labs/repl.cnf,开启二进制日志、中继日志,配置唯一server-id,开启 GTID 模式(后续使用):
# server1 核心配置
[mysqld@server1]
server-id=11
log-bin=server1-bin
relay-log=server1-relay-bin
gtid-mode=ON
enforce-gtid-consistency=ON
# server2 核心配置
[mysqld@server2]
server-id=12
log-bin=server2-bin
relay-log=server2-relay-bin
gtid-mode=ON
enforce-gtid-consistency=ON
# server3 核心配置
[mysqld@server3]
server-id=13
log-bin=server3-bin
relay-log=server3-relay-bin
gtid-mode=ON
enforce-gtid-consistency=ON
# server4 核心配置
[mysqld@server4]
server-id=14
log-bin=server4-bin
relay-log=server4-relay-bin
gtid-mode=ON
enforce-gtid-consistency=ON
4. 启动 MySQL 多实例
通过系统服务管理多实例,重新加载服务配置并启动所有实例:
# 编辑多实例服务配置(按需调整)
vim /usr/lib/systemd/system/mysqld@.service
# 重新加载系统服务
systemctl daemon-reload
# 启动所有MySQL实例
systemctl start mysqld@server1
systemctl start mysqld@server2
systemctl start mysqld@server3
systemctl start mysqld@server4
注:所有实例通过
--defaults-file=/labs/repl.cnf --defaults-group-suffix=@serverX启动,分别加载对应实例的配置。
三、实操一:基础主从复制配置(server1→server2)
实现单主单从基础复制拓扑,主库为 server1(3311),从库为 server2(3312),核心步骤为主库配置、从库配置、复制启动与验证。
1. 主库(server1)配置
(1)登录主库并设置提示符(便于区分节点)
mysql -uroot -h127.0.0.1 -P3311
# 设置提示符为1>,标识主库
1> PROMPT 1>;
(2)查看主库二进制日志位点
记录日志文件名与位置,作为从库同步的起始点:
1> SHOW MASTER STATUS\G
# 关键输出
File: server1-bin.000001 # 二进制日志文件名
Position: 155 # 日志写入位置
Executed_Gtid_Set: # 未开启GTID时为空
(3)创建并授权复制专用用户
创建repl用户,授予REPLICATION SLAVE权限,仅允许本地访问(生产环境建议限制从库 IP):
1> CREATE USER 'repl'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY 'oracle';
1> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'127.0.0.1';
1> FLUSH PRIVILEGES;
(4)主库导入测试数据
创建业务数据库并导入数据,作为同步测试源:
1> SOURCE /path/to/world.sql; # 导入world测试库
1> SHOW DATABASES; # 验证数据库创建成功
2. 从库(server2)配置
(1)登录从库并设置提示符
mysql -uroot -h127.0.0.1 -P3312
# 设置提示符为2>,标识从库
2> PROMPT 2>;
(2)配置主从复制参数
指定主库地址、端口、同步起始日志位点,与主库SHOW MASTER STATUS输出保持一致:
2> CHANGE MASTER TO
MASTER_HOST='127.0.0.1',
MASTER_PORT=3311,
MASTER_LOG_FILE='server1-bin.000001',
MASTER_LOG_POS=155;
(3)启动从库复制线程
启动 IO_THREAD 和 SQL_THREAD,开始从主库拉取并重放日志:
2> START SLAVE USER='repl' PASSWORD='oracle';
3. 主从复制状态验证
(1)主库验证复制连接
主库执行SHOW PROCESSLIST,查看是否有从库的 Binlog Dump 连接:
1> SHOW PROCESSLIST\G
# 关键输出:State为Master has sent all binlog to slave; waiting for more updates
(2)从库验证复制线程状态
从库执行SHOW PROCESSLIST,查看 IO/SQL 线程运行状态:
2> SHOW PROCESSLIST\G
# 关键输出:State为Slave has read all relay log; waiting for more updates
(3)验证数据同步结果
从库查看是否同步到主库的world数据库,确认数据一致:
# 主库查看数据
1> SELECT ID, Name FROM world.city ORDER BY ID DESC LIMIT 5;
# 从库查看数据,与主库完全一致即为同步成功
2> SHOW DATABASES; # 可见world库
2> SELECT ID, Name FROM world.city ORDER BY ID DESC LIMIT 5;
四、实操二:新增从库部署(基于 server2 新增 server3 从库)
在已有主从拓扑(server1→server2)基础上,新增 server3 作为 server2 的从库,核心难点为从库数据初始化 与同步位点获取,需通过备份实现数据一致性。
1. 从库(server2)全量备份
在 server2 上执行 mysqldump 备份,通过--master-data=2记录当前同步位点,仅备份业务库world:
mysqldump -uroot -h127.0.0.1 -P3312 --master-data=2 -B world > /tmp/server2.sql
注:
--master-data=2会在备份文件中以注释形式记录当前二进制日志位点,-B指定备份的数据库,此备份仅包含 world 库,不包含 mysql 系统库中的复制用户信息。
2. 查看备份文件中的同步位点
编辑备份文件,找到CHANGE MASTER TO注释行,记录日志文件名与位置:
vim /tmp/server2.sql
# 关键注释行,记录同步起始位点
-- CHANGE MASTER TO MASTER_LOG_FILE='server2-bin.000001', MASTER_LOG_POS=736159;
3. 新从库(server3)配置
(1)登录 server3 并设置提示符
mysql -uroot -h127.0.0.1 -P3313
3> PROMPT 3>;
(2)导入备份文件初始化数据
恢复 server2 的 world 库数据,保证新从库与主库数据基础一致:
3> SOURCE /tmp/server2.sql;
(3)配置复制参数并启动复制
基于备份文件中的位点,配置主库为 server2,启动复制线程:
# 配置复制参数
3> CHANGE MASTER TO
MASTER_HOST='127.0.0.1',
MASTER_PORT=3312,
MASTER_LOG_FILE='server2-bin.000001',
MASTER_LOG_POS=736159;
# 启动复制线程
3> START SLAVE USER='repl' PASSWORD='oracle';
4. 新增从库同步验证
(1)验证从库复制状态
3> SHOW SLAVE STATUS\G
# 关键输出:Slave_IO_Running=Yes、Slave_SQL_Running=Yes
(2)验证多级数据同步
主库 server1 执行数据变更,验证 server2、server3 是否逐级同步:
# 主库server1删除数据
1> DELETE FROM world.city WHERE ID>4070;
# server2验证数据已删除
2> SELECT ID, Name FROM world.city ORDER BY ID DESC LIMIT 5;
# server3验证数据已同步删除,与server2一致
3> SELECT ID, Name FROM world.city ORDER BY ID DESC LIMIT 5;
五、实操三:开启 GTID 并配置环形复制(server1→server2→server3→server1)
GTID(Global Transaction Identifier,全局事务标识符)为每个事务分配唯一标识,替代传统的「文件 + 位点」同步方式,实现自动定位同步位点 ,简化复制配置与故障切换。在此基础上搭建环形复制,实现多节点互相同步。
1. 开启 GTID 模式(所有节点)
(1)停止所有 MySQL 实例与复制线程
# 停止所有MySQL多实例
systemctl stop mysqld@server*
# 登录各节点,停止复制线程(若未停止)
1> STOP SLAVE;
2> STOP SLAVE;
3> STOP SLAVE;
(2)确认 GTID 配置已生效
检查/labs/repl.cnf中已配置以下 GTID 核心参数(实操二已配置):
gtid-mode=ON
enforce-gtid-consistency=ON # 强制GTID一致性,防止非GTID事务
(3)重启所有 MySQL 实例
systemctl start mysqld@server1
systemctl start mysqld@server2
systemctl start mysqld@server3
2. 传统复制升级为 GTID 复制(server1→server2)
将原有「文件 + 位点」复制升级为 GTID 复制,核心为清空旧日志历史 与开启自动定位。
(1)登录从库 server2,重置主库并配置 GTID 同步
2> STOP SLAVE; # 停止传统复制线程
2> RESET MASTER; # 清空旧的二进制日志与GTID历史
2> CHANGE MASTER TO MASTER_AUTO_POSITION=1; # 开启GTID自动定位
2> START SLAVE USER='repl' PASSWORD='oracle'; # 启动GTID复制线程
(2)验证 GTID 复制状态
2> SHOW SLAVE STATUS\G
# 关键输出:Master_Auto_Position=1、Slave_IO_Running=Yes、Slave_SQL_Running=Yes
3. 搭建 GTID 模式环形复制拓扑
配置环形复制:server1→server2→server3→server1,所有节点均为主库同时也是从库,核心为每个节点配置上游主库并开启 GTID 自动定位。
(1)配置 server2→server3 的 GTID 复制
# 登录server3,停止旧复制线程并重置
3> STOP SLAVE;
3> RESET MASTER;
# 配置主库为server2,开启GTID自动定位
3> CHANGE MASTER TO
MASTER_HOST='127.0.0.1',
MASTER_PORT=3312,
MASTER_AUTO_POSITION=1;
# 启动复制线程
3> START SLAVE USER='repl' PASSWORD='oracle';
(2)配置 server3→server1 的 GTID 复制
# 登录server1,停止旧复制线程并重置
1> STOP SLAVE;
1> RESET MASTER;
# 配置主库为server3,开启GTID自动定位
1> CHANGE MASTER TO
MASTER_HOST='127.0.0.1',
MASTER_PORT=3313,
MASTER_AUTO_POSITION=1;
# 启动复制线程
1> START SLAVE USER='repl' PASSWORD='oracle';
4. 环形复制状态与数据同步验证
(1)各节点验证 GTID 复制状态
每个节点执行SHOW SLAVE STATUS\G,确保Slave_IO_Running=Yes、Slave_SQL_Running=Yes、Master_Auto_Position=1。
(2)验证环形数据同步
任意节点执行数据变更,验证其他节点是否同步更新,实现环形互通:
# server2执行数据插入/更新
2> INSERT INTO world.city (Name, CountryCode, District, Population) VALUES ('TestCity', 'USA', 'California', 10000);
# server3验证数据已同步
3> SELECT * FROM world.city WHERE Name='TestCity';
# server1验证数据已同步
1> SELECT * FROM world.city WHERE Name='TestCity';
(3)查看节点 GTID 与 UUID
# 查看节点UUID,唯一标识GTID集群中的节点
2> SELECT @@server_uuid;
# 查看已执行的GTID事务
2> SHOW MASTER STATUS\G;
六、实操常见问题与解答
1. 备份文件中为何没有复制用户repl?
mysqldump 备份时通过-B world仅指定了业务库 world ,而复制用户repl存储在mysql 系统库中,因此不会被包含在备份文件中;且复制用户是在主库创建后通过复制同步到从库,并非备份文件自带。
2. 从库启动后Slave_IO_Running=No如何排查?
- 检查主从库
server-id是否唯一,无重复; - 验证复制用户密码是否正确,权限是否为
REPLICATION SLAVE; - 检查主库二进制日志是否开启(
log-bin); - 验证主从库网络连通性,端口是否开放;
- 检查从库配置的
MASTER_LOG_FILE和MASTER_LOG_POS是否与主库一致。
3. GTID 模式与传统复制模式的核心区别?
- 传统复制:基于「二进制日志文件 + 位点」定位同步起始点,需手动记录和配置,故障切换时需重新查找位点;
- GTID 复制:基于全局唯一事务 ID 定位,无需手动指定文件和位点,通过
MASTER_AUTO_POSITION=1实现自动定位,简化配置与故障切换,提升复制可靠性。
七、核心知识点总结
- MySQL 异步复制的核心是二进制日志 + 中继日志 ,通过 IO_THREAD 和 SQL_THREAD 实现主从数据同步,
server-id唯一是集群配置的前提; - 基础主从复制配置的核心步骤为:主库开启 binlog + 创建复制用户→记录主库位点→从库配置参数→启动复制线程→验证同步;
- 新增从库时,需通过
mysqldump --master-data=2实现数据初始化 + 同步位点记录,保证新从库与主库数据基础一致; - GTID 通过全局唯一事务 ID 替代传统「文件 + 位点」,实现自动定位同步位点,核心配置为
gtid-mode=ON+MASTER_AUTO_POSITION=1; - 环形复制是多节点互为主从的拓扑模式,需基于 GTID 实现,适用于多区域数据同步场景,配置核心为每个节点指定上游主库并开启 GTID 自动定位;
- 复制验证的核心标准为:从库
Slave_IO_Running=Yes、Slave_SQL_Running=Yes,且各节点数据完全一致。