MySQL 主从复制核心原理详解
概述
主从复制(Replication)是 MySQL 最基础也是最重要的高可用架构组件。通过主从复制,可以将主库(Master)的数据变更同步到一个或多个从库(Slave),实现读写分离、数据备份和故障切换。
复制的核心流程
MySQL 主从复制基于 Binlog,核心分为三个步骤:
主库(Master) 从库(Slave)
│ │
│ 1. 事务提交 │
│ ├── 写入 Binlog │
│ └── 返回成功 │
│ │
│ 2. 从库 I/O 线程 │
│ ←──── 拉取 Binlog ────── │
│ 请求 binlog dump │
│ │
│ 3. I/O 线程写入 Relay Log(中继日志)
│ │
│ 4. SQL 线程读取 Relay Log 并回放
│ │
│ 5. 从库数据与主库一致 ✅
三个关键线程
| 线程 | 运行位置 | 作用 |
|---|---|---|
| Binlog Dump 线程 | 主库 | 负责将 Binlog 发送给从库 |
| I/O 线程 | 从库 | 连接主库,拉取 Binlog,写入 Relay Log |
| SQL 线程 | 从库 | 读取 Relay Log,重放 SQL/行变更 |
复制的工作细节
步骤 1:主库写入 Binlog
-- 主库上执行
UPDATE users SET balance = 100 WHERE id = 1;
-- 主库 Binlog 记录
# at 123456
#2026-05-18 10:00:00 server id 1 end_log_pos 123789 ...
UPDATE `test`.`users` SET @3=100 WHERE @1=1
步骤 2:从库 I/O 线程拉取
-- 从库启动连接
CHANGE MASTER TO
MASTER_HOST='192.168.1.10',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=123456;
START SLAVE;
I/O 线程的行为:
– 连接到主库的 Binlog Dump 线程
– 从指定位置(MASTER_LOG_POS)开始拉取 Binlog
– 持续接收新的 Binlog 事件
– 写入本地的 Relay Log
步骤 3:Relay Log(中继日志)
Relay Log 是从库本地保存的、从主库拉取来的 Binlog 副本:
从库文件系统:
relay-log.000001 ← I/O 线程写入
relay-log.000002
relay-log.index ← Relay Log 索引
步骤 4:SQL 线程回放
SQL 线程持续读取 Relay Log 并执行其中的 SQL/行变更:
-- SQL 线程内部执行的等效操作
UPDATE `test`.`users` SET balance = 100 WHERE id = 1;
步骤 5:记录复制进度
SQL 线程执行完后,更新复制进度信息:
SHOW SLAVE STATUS\G
-- 输出中包含:
-- Relay_Log_Pos: 当前 Relay Log 位置
-- Exec_Master_Log_Pos: 当前已执行的 Binlog 位置
-- Seconds_Behind_Master: 从库落后主库的秒数
复制的关键信息查看
-- 主库:查看当前 Binlog 位置
SHOW MASTER STATUS;
-- +------------------+----------+--------------+------------------+
-- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
-- +------------------+----------+--------------+------------------+
-- | mysql-bin.000015 | 12345678 | | |
-- +------------------+----------+--------------+------------------+
-- 从库:查看复制状态
SHOW SLAVE STATUS\G
-- 重点关注:
-- Slave_IO_Running: Yes ← I/O 线程是否正常
-- Slave_SQL_Running: Yes ← SQL 线程是否正常
-- Seconds_Behind_Master: 0 ← 延迟秒数
-- Last_IO_Error: ← I/O 线程最后错误
-- Last_SQL_Error: ← SQL 线程最后错误
复制的配置
主库配置
# /etc/mysql/my.cnf(主库)
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
sync_binlog = 1
-- 创建复制账号
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
从库配置
# /etc/mysql/my.cnf(从库)
[mysqld]
server-id = 2 -- 必须与主库不同
relay_log = /var/log/mysql/relay-log
log_bin = /var/log/mysql/mysql-bin -- 从库也可开启 binlog
read_only = ON -- 从库只读(防止误写)
-- 从库设置主库信息并启动
CHANGE MASTER TO
MASTER_HOST='192.168.1.10',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;
-- 检查状态
SHOW SLAVE STATUS\G
面试要点
- 复制三线程:主库 Binlog Dump 线程 + 从库 I/O 线程 + 从库 SQL 线程
- 数据流:Binlog(主库)→ I/O 线程拉取 → Relay Log(从库)→ SQL 线程回放
- 关键在于 Binlog:复制的一切都基于 Binlog
- server-id 必须不同:否则无法正常复制
SHOW SLAVE STATUS是排障第一命令- 基础复制是异步的:主库提交后不等从库确认就返回成功
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容