Mysql主从复制
一、什么是 MySQL 主从复制?
MySQL 主从复制是基于二进制日志(binlog)实现的异步 / 半同步数据复制技术,核心作用是:一台主库(Master)写入,多台从库(Slave)同步复制数据,是 MySQL 高可用、读写分离、数据备份、负载均衡的基础。
简单来说,就是一台主库负责处理数据写入,一台或多台从库自动同步主库的数据,承担数据读取的架构模式。
我们日常业务中,数据库的增、删、改操作全部走主库,查询请求分流到从库,既解决了单库读写压力瓶颈,也实现了数据实时备份。
主从复制的核心价值主要有四点:
- 读写分离,提升并发性能:将高频查询请求剥离,主库专注写操作,大幅提升数据库整体吞吐量
- 实时热备份,防止数据丢失:从库实时同步主库数据,无需频繁冷备份,规避主库宕机数据丢失风险
- 支撑高可用、故障切换:主库故障时,可快速将从库提升为主库,保障业务不中断
- 支持水平扩容:通过增加从库数量,无限扩展数据库查询能力
二、主从复制核心底层原理
主从复制的本质很简单:主库记录数据变更日志,从库主动拉取日志并重新执行,最终实现数据一致。
- 核心组件
- 主库 Binlog(二进制日志):主库的核心日志,会记录所有增、删、改数据变更操作,不记录普通查询语句,是主从同步的数据源
- 从库 IO 线程:专门负责和主库建立连接,主动拉取主库的 Binlog 日志,将日志内容写入本地的中继日志(Relay Log)
- 从库 SQL 线程:读取本地中继日志,逐条重放日志中的数据操作,让从库数据和主库保持同步
- 同步执行流程
- 客户端向主库执行 INSERT、UPDATE、DELETE 等写操作
- 主库执行 SQL 语句,完成数据写入,同时将操作记录到本地 Binlog 日志中
- 从库的 IO 线程持续监听主库,主动拉取最新的 Binlog 日志
- 主库将新增的日志数据推送至从库,从库 IO 线程将日志写入本地 Relay Log(中继日志)
- 从库 SQL 线程实时读取中继日志,逐条执行日志中的数据操作
- 最终主从库数据完全一致,同步完成
核心总结:主库负责记日志,从库负责拉日志、执行日志,全程是从库主动拉取,而非主库主动推送。
三、Binlog 三种日志格式
Binlog 的记录格式,直接决定主从同步的准确性和效率,三种格式各有优劣:
- STATEMENT(语句模式)
直接记录客户端执行的原生 SQL 语句。优点是日志体积小、占用资源少;缺点是部分函数、随机语句、存储过程执行后,主从数据可能出现不一致,同步精度差。 - ROW(行模式)
不记录 SQL 语句,直接记录每一行数据的变更前后状态。同步精度极高,几乎不会出现数据不一致问题,适配所有业务场景;唯一缺点是日志体积会稍大。 - MIXED(混合模式)
是前两种模式的结合体,MySQL 会自动判断场景:普通语句用 STATEMENT 模式,特殊风险语句自动切换为 ROW 模式。兼顾体积和准确性,但不如纯 ROW 模式稳定。
四、三种主从同步模式
- 异步复制—— MySQL 默认模式
异步复制是 MySQL 原生默认的同步模式,核心特点是主库与从库的日志同步完全解耦,主库无需等待从库任何响应,全程无阻塞写入。
执行时序:
- 客户端向主库提交事务;
- 主库执行事务,成功提交后,将本次事务变更记录写入本地 Binlog 日志;
- 主库立即返回「执行成功」给客户端,本次请求结束;
- 后台异步线程继续工作:从库 IO 线程后续拉取主库 Binlog,写入本地 Relay Log;
- 从库 SQL 线程重放日志,完成数据同步。
整个过程中,主库的写入响应和从库的同步行为是异步并行的,两者互不干扰。
核心优缺点:
- 优点:零阻塞、写入性能最高、吞吐量最大,无额外网络等待开销,适配高并发写入场景。
- 缺点:数据一致性最弱、存在丢数据风险。主库返回成功时,数据仅存在主库本地,从库大概率还未同步日志。如果此时主库瞬间宕机、磁盘损坏,未同步的 Binlog 会直接丢失,从库无法补齐数据,造成数据永久缺失。
- 半同步复制—— 生产推荐
半同步复制是为了解决异步复制丢数据的问题诞生的,也是目前互联网公司核心业务的标配模式。它在性能和数据安全之间做了完美平衡,既不会像全同步复制那样严重拖垮性能,又能杜绝绝大多数数据丢失风险。
核心定义:主库事务提交、写入 Binlog 后,必须阻塞等待至少一台从库确认接收日志并落盘,收到从库 ACK 应答后,才会响应客户端执行成功。
执行时序:
- 客户端提交写事务到主库;
- 主库执行事务,完成本地数据落盘,并写入本地 Binlog 日志;
- 主库进入短暂阻塞状态,暂停响应客户端,等待从库回执;
- 从库 IO 线程拉取该条 Binlog,成功写入本地 Relay Log 并刷盘;
- 从库立即向主库返回 ACK 确认包(仅确认日志落盘,不等待 SQL 执行);
- 主库收到 ACK,结束阻塞,返回「执行成功」给客户端;
- 后续从库后台异步执行 Relay Log,完成数据同步。
关键核心细节:
- 阻塞临界点:主库只等「从库日志落盘确认」,绝不等待从库执行完事务,极大降低了性能损耗;
- 容错机制:主库默认超时时间为 1 秒(参数 rpl_semi_sync_master_timeout),若 1 秒内未收到从库 ACK,会自动降级为异步复制,避免大量请求阻塞、业务雪崩;
- 数据安全保障:只要客户端收到成功响应,就意味着数据同时存在「主库+至少一台从库」双份磁盘落地,主库宕机也不会丢失数据。
核心优缺点: - 优点:数据安全性极高,几乎零丢数据风险;性能损耗极低,仅增加少量网络等待耗时;支持自动降级,兼容极端异常场景。
- 缺点:相比异步复制有轻微网络延迟,超高并发极致压测场景下性能略低于异步复制。
- 全同步复制
全同步复制是安全级别最高的同步模式,也是最严苛的同步机制,彻底解决数据不一致、数据丢失问题,但牺牲了极致的写入性能,线上业务基本不会采用。
核心定义:主库事务提交后,必须等待集群中所有从库全部完成「日志接收、落盘、事务重放执行」,所有从库全部返回确认 ACK 后,主库才会响应客户端执行成功。
执行时序:
- 客户端提交写事务到主库;
- 主库执行事务、写入 Binlog,进入长时间阻塞状态;
- 所有从库分别拉取 Binlog,写入 Relay Log,执行 SQL 完成数据更新;
- 每一台从库全部执行完成后,依次向主库返回确认包;
- 主库收集完所有从库的 ACK 确认,才解除阻塞,返回执行成功。
核心优缺点:
- 优点:全局数据强一致性,主从所有节点数据实时完全一致,零延迟、零丢失,无任何数据不一致风险。
- 缺点:性能缺陷致命。集群从库数量越多,阻塞时间越长;只要有一台从库卡顿、故障、网络延迟,所有主库写入请求都会被阻塞,直接拖垮整个业务写入能力。
重点记住:MySQL 主从复制只会同步「开启同步之后的新数据」,不会自动同步历史存量数据。
如果主库已经运行一段时间,存在大量历史数据,直接配置主从同步、不做全量备份,最终结果就是:从库只有后续新增的数据,缺失所有历史数据,主从数据彻底不一致,甚至出现主键冲突、同步中断的问题。
常见问题
- 同步延迟:多由大事务、主库写入并发过高、从库硬件配置偏低导致,可通过拆分大事务、升级从库配置、开启并行复制优化
- 同步中断、主键冲突:大多是从库手动写入数据、历史数据不一致导致,生产环境务必设置从库只读
- IO 线程异常:多为主从网络不通、同步账号密码错误、主库 Binlog 日志被清理导致
五.MySQL 主从复制 模式分类
MySQL 主从复制模式 = 同步机制 + 定位方式 + 记录格式 + 并行能力 + 架构形态
-
按事务一致性
异步复制
半同步复制
全同步复制 -
按 binlog 定位方式
传统 File & Position 模式
GTID 模式(生产主流) -
按 binlog 记录格式
行模式(ROW)
语句模式(STATEMENT)
混合模式(MIXED) -
按并行复制能力
单线程复制
多线程并行复制 -
高级复制架构
组复制(MGR)
主主复制
级联复制
五、MySQL 一主两从,传统 File&Position 模式 + 异步复制
环境:
-
主库 (Master):192.168.1.131
-
从库 1 (Slave1):192.168.1.132
-
从库 2 (Slave2):192.168.1.133
第一步:三台虚拟机 时间必须同步
主从时间不一致,复制会直接异常、延迟、报错。
所有机器执行(131/132/133 都运行)
- 安装时间同步工具
yum install -y chrony
- 启动并开机自启
systemctl start chronyd
systemctl enable chronyd
- 查看时间是否同步
date
三台机器时间误差必须 < 1 秒。
第二步:关闭防火墙 / 开放 3306(三台都执行)
临时关闭防火墙
systemctl stop firewalld
禁止开机启动
systemctl disable firewalld
关闭SELINUX
setenforce 0
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
第三步:保证主从初始数据完全一致(核心步骤)
原理
-
主库锁表 → 备份数据 → 解锁
-
把备份文件发送到两个从库并恢复
-
恢复后主从数据 100% 一致
操作步骤
- 主库(131)锁表,禁止写入
FLUSH TABLES WITH READ LOCK;
执行后不要退出这个 MySQL 窗口! 锁表状态会保持。
- 查看主库 binlog 位置(记录下来,从库要用)
SHOW MASTER STATUS;
你会看到类似:
File | Position
binlog.000001 | 1148
记下来!等会儿配置从库要用。
- 新开一个 SSH 窗口,主库全量备份
mysqldump -uroot -p --all-databases --master-data=2 --single-transaction > all_db.sql
- 主库解锁
UNLOCK TABLES;
- 把备份文件发送到 从库 1、从库 2
发送到132
scp all_db.sql root@192.168.1.132:/root/
发送到133
scp all_db.sql root@192.168.1.133:/root/
- 从库 1(132)恢复数据
mysql -uroot -p < /root/all_db.sql
- 从库 2(133)恢复数据
mysql -uroot -p < /root/all_db.sql
第四步:配置主库(131)my.cnf
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW
binlog_ignore_db = mysql
binlog_ignore_db = information_schema
binlog_ignore_db = performance_schema
重启 MySQL
systemctl restart mysqld
主库创建复制账号(给从库用)
CREATE USER 'repl'@'%' IDENTIFIED BY 'Aa123456.';
GRANT REPLICATION SLAVE ON . TO 'repl'@'%';
FLUSH PRIVILEGES;
第五步:配置从库 1(132)
[mysqld]
server-id = 2
relay-log = relay-bin
read_only = 1
super_read_only = 1
重启 MySQL
systemctl restart mysqld
执行主从关联命令
CHANGE MASTER TO
MASTER_HOST='192.168.88.131',
MASTER_USER='repl',
MASTER_PASSWORD='Aa123456.',
MASTER_LOG_FILE='binlog.000001', # 你刚才记录的FILE
MASTER_LOG_POS=1148; # 你刚才记录的START SLAVE;
第六步:配置从库 2(133)
[mysqld]
server-id = 3
relay-log = relay-bin
read_only = 1
super_read_only = 1
重启 MySQL
systemctl restart mysqld
执行主从关联命令
CHANGE MASTER TO
MASTER_HOST='192.168.88.131',
MASTER_USER='repl',
MASTER_PASSWORD='Aa123456.',
MASTER_LOG_FILE='binlog.000001', # 你刚才记录的FILE
MASTER_LOG_POS=1148; # 你刚才记录的START SLAVE;
第七步:验证主从是否成功(两个从库都执行)
SHOW SLAVE STATUS\G
看到这两个都为 YES 就成功了:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
第八步:验证主从数据是否真的一致
主库创建库 + 表 + 插入数据
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE t1(id INT);
INSERT INTO t1 VALUES(1);
从库直接查询
USE testdb;
SELECT * FROM t1;
能查到数据 = 主从同步成功!
五.总结
-
主从复制核心是binlog + 3 个线程,实现主库数据自动同步到从库
-
生产环境标配:主从架构 + 读写分离 + 半同步复制
-
搭建关键:server-id 唯一、binlog 开启、主从数据初始一致、复制账号权限正确
-
核心验证:
SHOW SLAVE STATUS两个线程必须为YES -
三台时间必须同步(chrony)
-
主库锁表备份 → 从库恢复 → 数据 100% 一致
-
server-id 不能重复(1、2、3)
-
从库配置
read_only防止误写 -
检查
SHOW SLAVE STATUS\G两个 YES = 成功

浙公网安备 33010602011771号