MySQL 主从复制核心原理详解

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

面试要点

  1. 复制三线程:主库 Binlog Dump 线程 + 从库 I/O 线程 + 从库 SQL 线程
  2. 数据流:Binlog(主库)→ I/O 线程拉取 → Relay Log(从库)→ SQL 线程回放
  3. 关键在于 Binlog:复制的一切都基于 Binlog
  4. server-id 必须不同:否则无法正常复制
  5. SHOW SLAVE STATUS 是排障第一命令
  6. 基础复制是异步的:主库提交后不等从库确认就返回成功
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容