主从复制原理
导学
单台 MySQL 服务器既要处理写请求又要处理读请求,压力会越来越大。主从复制(Replication)让一台主库(Master)负责写,多台从库(Slave)负责读,是 MySQL 扩展读性能、实现高可用的最基础架构。理解 binlog、relay log 和复制线程的工作机制,是运维 MySQL 的必修课。
定义
主从复制:MySQL 将主库的数据变更记录到二进制日志(binlog),从库通过 I/O 线程读取 binlog 并写入中继日志(relay log),再由 SQL 线程重放 relay log 中的事件,实现数据同步。
核心概念
| 组件 | 作用 | 位置 |
|---|---|---|
| binlog | 记录主库所有数据变更(DDL + DML) | 主库 |
| relay log | 从库暂存从主库接收的 binlog 事件 | 从库 |
| I/O 线程 | 连接主库,读取 binlog 并写入 relay log | 从库 |
| SQL 线程 | 读取 relay log,按顺序重放事件 | 从库 |
| master.info | 记录从库连接主库的配置和读取位置 | 从库 |
| relay-log.info | 记录 SQL 线程执行到 relay log 的位置 | 从库 |
复制模式
| 模式 | 特点 | 适用场景 |
|---|---|---|
| 异步复制(默认) | 主库不等待从库确认,性能最好,但可能丢数据 | 读扩展,允许秒级延迟 |
| 半同步复制 | 主库等待至少一个从库确认收到 binlog 才返回 | 数据安全优先,容忍轻微延迟 |
| GTID 复制 | 基于全局事务 ID,自动定位复制点,故障切换简单 | 5.6+ 推荐,复杂拓扑必备 |
SQL 示例
场景一:配置异步复制(基础版)
主库配置(my.cnf):
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW
从库配置(my.cnf):
[mysqld]
server-id = 2
relay-log = mysql-relay-bin
read-only = 1
server-id必须全局唯一,read-only=1防止从库被误写入(有 SUPER 权限的用户仍可写)。
场景二:主库创建复制用户
执行语句:
-- 在主库上执行
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
结果解读:
REPLICATION SLAVE权限是从库连接主库读取 binlog 的最低权限- 生产环境应将
%替换为从库的具体 IP 地址
场景三:获取主库 binlog 位置
执行语句:
-- 在主库上执行,锁定表防止数据变更
FLUSH TABLES WITH READ LOCK;
-- 查看当前 binlog 文件名和位置
SHOW MASTER STATUS;
操作后结果:
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
|---|---|---|---|
| mysql-bin.000001 | 154 |
结果解读:
File:当前正在写入的 binlog 文件名Position:当前写入位置(字节偏移量)- 从库需要从
mysql-bin.000001:154这个位置开始同步 - 记录后执行
UNLOCK TABLES;解除锁定
场景四:从库启动复制
执行语句:
-- 在从库上执行
CHANGE MASTER TO
MASTER_HOST = '192.168.1.10',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'repl_password',
MASTER_LOG_FILE = 'mysql-bin.000001',
MASTER_LOG_POS = 154;
START SLAVE;
查看复制状态:
SHOW SLAVE STATUS\G
关键字段:
| 字段 | 含义 | 正常状态 |
|---|---|---|
Slave_IO_Running | I/O 线程是否运行 | Yes |
Slave_SQL_Running | SQL 线程是否运行 | Yes |
Seconds_Behind_Master | 从库延迟秒数 | 0 或较小值 |
Last_IO_Error / Last_SQL_Error | 最近错误 | 空 |
结果解读:
Slave_IO_Running = No:网络问题、权限问题、server-id 冲突Slave_SQL_Running = No:主从数据不一致、SQL 执行错误(如重复键)Seconds_Behind_Master = NULL:复制可能已停止或 I/O 线程异常
场景五:GTID 复制配置(推荐)
主库和从库配置(my.cnf):
[mysqld]
gtid-mode = ON
enforce-gtid-consistency = ON
log-bin = mysql-bin
server-id = 1 -- 主库为1,从库为2
从库启动 GTID 复制:
-- 无需指定 MASTER_LOG_FILE/POS,GTID 自动定位
CHANGE MASTER TO
MASTER_HOST = '192.168.1.10',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'repl_password',
MASTER_AUTO_POSITION = 1;
START SLAVE;
结果解读:
MASTER_AUTO_POSITION = 1启用 GTID 自动定位,无需手动指定 binlog 文件和位置- GTID 格式:
uuid:transaction_id,如3e11fa47-71ca-11e1-9e33-c80aa9429562:23 - 故障切换时,新主库的 GTID 集合可以自动判断从库是否需要同步缺失数据
场景六:排查复制延迟
执行语句:
-- 查看从库延迟
SHOW SLAVE STATUS\G
-- 关注 Seconds_Behind_Master
-- 查看 SQL 线程正在执行的事件
SHOW PROCESSLIST;
-- 关注 User=system user, Command=Binlog Dump / SQL 线程
-- 查看 relay log 堆积情况
SHOW VARIABLES LIKE 'relay_log%';
常见延迟原因:
| 原因 | 表现 | 解决方向 |
|---|---|---|
| 主库写入量过大 | Seconds_Behind_Master 持续增长 | 增加从库、拆分写入 |
| 从库单线程重放 | SQL 线程 CPU 100% | 5.7 开启多线程复制 slave_parallel_workers |
| 大事务 | 某条 SQL 执行时间长 | 拆分大事务、避免 DELETE 全表 |
| 从库配置差 | I/O 或 CPU 瓶颈 | 提升从库硬件 |
常见误区
| 误区 | 正解 |
|---|---|
| "主从复制是实时同步的" | 不是。异步复制有延迟(毫秒到秒级),Seconds_Behind_Master 显示的是估算延迟。 |
"从库设为 read-only 就完全不能写了" | 不是。read_only=1 只限制普通用户,有 SUPER 权限的用户(如 root)仍可写入。 |
| "binlog 只记录 INSERT/UPDATE/DELETE" | 不是。binlog 记录所有数据变更,包括 DDL(CREATE/ALTER/DROP)和 DML。 |
"复制断了可以直接 START SLAVE 恢复" | 不一定。如果主从数据已不一致(如主库插入了从库已存在的数据),START SLAVE 会报错。需要先修复数据或跳过错误。 |
| "GTID 复制比传统复制慢" | 不是。GTID 只是定位方式不同,传输和重放性能基本一致。GTID 的优势是故障切换和拓扑管理。 |
| "一台主库可以配无数台从库" | 理论上可以,但每台从库都会连接主库读取 binlog,过多从库会拖垮主库网络。建议通过"级联复制"(从库再带从库)扩展。 |
面试考点
Q:MySQL 主从复制的原理?
主库将数据变更写入 binlog;从库的 I/O 线程连接主库,读取 binlog 写入 relay log;SQL 线程读取 relay log 按顺序重放事件,保持数据一致。默认是异步复制,主库不等待从库确认。
Q:binlog 的三种格式区别?
STATEMENT:记录 SQL 语句,体积小但某些语句(如 UUID()、NOW())在主从执行结果可能不一致。ROW:记录每行数据的变更,体积大但数据一致性最好,5.7 推荐。MIXED:MySQL 自动选择 STATEMENT 或 ROW,折中方案。
Q:主从延迟怎么排查?
SHOW SLAVE STATUS看Seconds_Behind_Master;2.SHOW PROCESSLIST看 SQL 线程状态;3. 检查主库写入量是否突增;4. 检查从库硬件是否瓶颈;5. 5.7 可开启slave_parallel_workers多线程重放。
Q:GTID 复制的好处?
- 自动定位复制点,无需手动指定 binlog 文件和位置;2. 故障切换简单,新主库可以自动判断从库数据是否完整;3. 避免传统复制中
CHANGE MASTER TO指定错误位置导致数据错乱。
Q:从库可以执行写入操作吗?
可以但不推荐。
read_only=1只限制普通用户。如果从库写入数据与主库冲突(如主键重复),会导致 SQL 线程报错,复制中断。
小结
- 主从复制通过 binlog → relay log → SQL 线程重放实现数据同步
- 异步复制性能最好但可能丢数据,半同步复制平衡安全与性能,GTID 复制简化运维
- 配置复制需要:唯一 server-id、binlog 开启、复制用户、CHANGE MASTER TO、START SLAVE
- 排查复制问题看
SHOW SLAVE STATUS的Slave_IO_Running、Slave_SQL_Running、Seconds_Behind_Master - GTID 是 5.6+ 的推荐方案,自动定位复制点,故障切换更可靠
下一章引子:复制解决了读扩展,但数据安全还需要备份机制——当主库磁盘损坏、误删数据时,只有备份能救命。