0%

MySQL主从复制

MySQL 主从复制详解:原理、配置与架构

MySQL 主从复制是分布式数据库架构的基础,通过将主库(Master)的数据异步复制到从库(Slave),实现读写分离、负载均衡和数据备份。本文详细解析主从复制的核心原理、复制方式、配置步骤及常见架构。

主从复制的核心概念与线程

主从复制依赖三个关键线程协同工作,实现数据从 Master 到 Slave 的传递与应用:

线程类型 所在节点 核心作用
Binlog Dump Thread Master 监测 Master 的二进制日志(binlog)变化,当有数据更新时,将 binlog 事件发送给 Slave。
I/O Thread Slave 连接 Master,接收 Binlog Dump Thread 发送的 binlog 事件,写入 Slave 的中继日志(relay log)。
SQL Thread Slave 读取中继日志中的 binlog 事件,解析并执行 SQL 语句,将 Master 的数据变更应用到 Slave。

主从复制的三种方式

根据数据同步的时效性和一致性保障,主从复制分为以下三种方式:

1. 异步复制(默认方式)

  • 原理:Master 执行事务后,将变更写入 binlog 即返回成功,无需等待 Slave 确认接收。
  • 特点:
    • 性能最优(无等待延迟)。
    • 存在数据不一致风险(若 Master 崩溃,Slave 可能未收到最新 binlog)。
  • 适用场景:对数据一致性要求不高,优先追求写入性能的场景(如日志存储)。

2. 同步复制

  • 原理:Master 执行事务后,需等待所有 Slave 确认数据已写入本地中继日志,才返回成功。
  • 特点:
    • 数据一致性最强(无丢失风险)。
    • 性能极差(Master 需等待所有 Slave 响应,延迟随 Slave 数量增加而剧增)。
  • 适用场景:几乎不使用(仅极端要求一致性的场景,如金融核心交易)。

3. 半同步复制(MySQL 5.5+ 新增)

  • 原理:Master 执行事务后,只需等待至少一个 Slave 确认已接收 binlog 并写入中继日志,即返回成功(无需等待 Slave 执行)。
  • 特点:
    • 平衡一致性与性能(仅丢失最多一个事务)。
    • 超时自动降级为异步复制(避免 Master 长期阻塞)。
  • 适用场景:大多数业务场景(如电商订单、用户数据),兼顾性能与数据安全性。
半同步复制的配置
  1. 安装插件

    1
    2
    3
    4
    5
    -- Master 安装半同步主库插件
    INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

    -- Slave 安装半同步从库插件
    INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
  2. 启用插件my.cnf 配置,永久生效):

    1
    2
    3
    4
    5
    6
    7
    8
    -- Master 配置
    [mysqld]
    rpl-semi-sync-master-enabled=1 # 启用半同步
    rpl-semi-sync-master-timeout=2000 # 超时时间(毫秒),超时后降级为异步

    -- Slave 配置
    [mysqld]
    rpl-semi-sync-slave-enabled=1 # 启用半同步
  3. 验证状态

    1
    2
    3
    4
    5
    -- 查看 Master 半同步状态(1 为活跃)
    SHOW STATUS LIKE 'rpl_semi_sync_master_status';

    -- 查看 Slave 半同步状态
    SHOW STATUS LIKE 'rpl_semi_sync_slave_status';
  • rpl_semi_sync_master_clients 展示支持和注册半同步复制的已连接的slave数量
  • rpl_semi_sync_master_status master的半同步复制状态,1是活动状态,0是非活动状态
  • rpl_semi_sync_slave_status slave的半同步复制状态,1是活动状态,0是非活动状态
  • rpl_semi_sync_master_yes_tx 显示从服务器确认的成功提交数量
  • rpl_semi_sync_master_no_tx 显示从服务器确认的不成功提交数量

主从复制的工作原理

主从复制的核心是通过 binlog 传递数据变更,完整流程如下:

  1. Master 写入 binlog
    Master 执行 INSERT/UPDATE/DELETE 等操作后,将变更记录为 “binlog 事件”,写入二进制日志(binlog)。
  2. Slave 接收 binlog
    Slave 的 I/O 线程连接 Master,请求从指定 binlog 位置(Master_Log_FileRead_Master_Log_Pos)开始同步。
    Master 的 Binlog Dump Thread 读取 binlog 事件,发送给 Slave 的 I/O 线程,后者将事件写入中继日志(relay log)。
  3. Slave 应用变更
    Slave 的 SQL 线程读取中继日志中的 binlog 事件,解析为 SQL 语句并执行,最终与 Master 数据保持一致。
  4. 状态同步
    Slave 定期向 Master 汇报已执行的 binlog 位置(Exec_Master_Log_Pos),Master 记录 Slave 的同步进度。

关键命令与状态变量

Master 常用命令

1
2
3
4
5
6
7
8
9
-- 查看 Master 二进制日志列表
SHOW MASTER LOGS;

-- 查看当前 binlog 位置(主从配置的关键参数)
SHOW MASTER STATUS;
-- 输出:File(当前 binlog 文件名)、Position(当前写入位置)

-- 重置 binlog(删除所有历史 binlog,谨慎使用)
RESET MASTER;

Slave 常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-- 配置主从关系
CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_USER='repl_user', -- 主库授权的复制用户
MASTER_PASSWORD='repl_pass',
MASTER_LOG_FILE='master_bin.000001', -- 从该 binlog 开始同步
MASTER_LOG_POS=154; -- 从该位置开始同步

-- 启动/停止复制
START SLAVE;
STOP SLAVE;

-- 查看 Slave 复制状态(核心命令)
SHOW SLAVE STATUS \G;
-- 重要字段有
-- Slave_IO_State 当前运行的IO线程状态
-- Master_Log_File、Read_Master_Log_Pos master的binlog读取位置
-- Relay_Log_File、Relay_Log_Pos 从服务器中继日志位置
-- Relay_Master_Log_File、Exec_Master_Log_Pos master的执行位置,如果从服务器有延迟的话,Exec_Master_Log_Pos的值可能会小于Read_Master_Log_Pos的值
-- Slave_SQL_Running 表示slave的sql线程是否在运行
-- Slave_IO_Running 表示slave的IO线程是否在运行
-- Last_IO_Errno、Last_IO_Error 显示IO线程最近的错误
-- Last_SQL_Errno、Last_SQL_Error 显示SQL线程最近的错误
-- Connect_Retry 两次重连的时间间隔
-- Relay_Log_Space 所有中继日志文件的总大小
-- Seconds_Behind_Master 事件执行和事件写入Master二进制日志之间的间隔时间,从服务器落后主服务器的时间,指的是从服务器上最后执行的事件和中继日志中复制过来的主服务器二进制日志的最后一个事件之间相隔的秒数
SHOW SLAVE STATUS 关键字段:
  • Slave_IO_Running:I/O 线程状态(Yes 表示正常)。
  • Slave_SQL_Running:SQL 线程状态(Yes 表示正常)。
  • Seconds_Behind_Master:Slave 落后 Master 的秒数(0 表示无延迟)。
  • Last_IO_Error/Last_SQL_Error:I/O/SQL 线程的错误信息(排查故障用)。

状态变量(监控复制健康度)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
-- Master 状态:复制用户连接数
SHOW STATUS LIKE 'Threads_connected';
-- 显示show master status命令执行的次数
show status like 'com_show_master_status'
-- 显示change master命令执行的次数
show status like 'com_change_master'

-- Slave 状态:复制延迟相关
SHOW STATUS LIKE 'Slave_retried_transactions'; -- SQL 线程重试次数
SHOW STATUS LIKE 'Slave_running'; -- 复制是否正常运行(On/Off)
-- show slave status命令执行的次数
show status like 'com_show_slave_status'
-- show slave hosts命令执行的次数
show status like 'com_show_slave_hosts'
-- slave start命令执行的次数
show status like 'com_slave_start'
-- slave stop命令执行的次数
show status like 'com_slave_stop'
-- 当前master的心跳检测的间隔时间的配置信息
show status like 'slave_heartbeat_period'
-- slave的sql线程使用临时表的数量,如果该值过高,说明slave负载过重
show status like 'slave_open_temp_tables'
-- 从master回复的心跳数,该值应该与心跳检测间隔时间一致,因为slave重新启动会在心跳间隔时断开
show status like 'slave_received_heartbeats'
-- slave启动后sql线程重试事务的次数
show status like 'slave_retried_transactions'
-- 如果slave连接到master,而且io线程和sql线程无错误地执行,则该值为on
show status like 'slave_running'

主从复制的配置示例

1. 一主一从架构(基础架构)

适用于读多写少场景,Master 负责写,Slave 负责读。

(1)Master 配置(my.cnf
1
2
3
4
5
6
[mysqld]
server-id=1 # 唯一标识(必填,不可与 Slave 重复)
log-bin=master_bin # 启用 binlog(主从复制的基础)
binlog-do-db=test # 仅同步 test 数据库(可选)
binlog-ignore-db=mysql # 忽略 mysql 系统库(可选)
sync_binlog=1 # 事务提交时立即刷写 binlog 到磁盘(增强安全性)
(2)创建复制用户
1
2
3
-- Master 授权 Slave 连接
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'slave_ip' IDENTIFIED BY 'repl_pass';
FLUSH PRIVILEGES;
(3)Slave 配置(my.cnf
1
2
3
4
5
[mysqld]
server-id=2 # 唯一标识(与 Master 不同)
relay_log=relay_bin # 中继日志文件名(可选,默认自动生成)
read_only=1 # 从库只读(避免误写,可选)
replication-do-db=test # 仅同步 test 数据库(与 Master 对应)
(4)启动复制
1
2
3
4
5
6
7
8
9
10
11
12
-- Slave 执行(使用 Master 的 SHOW MASTER STATUS 结果)
CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_USER='repl_user',
MASTER_PASSWORD='repl_pass',
MASTER_LOG_FILE='master_bin.000001',
MASTER_LOG_POS=154;

START SLAVE;

-- 验证状态(需 Slave_IO_Running 和 Slave_SQL_Running 均为 Yes)
SHOW SLAVE STATUS \G;

2. 双主架构(解决单点问题)

两个 Master 互为主从,避免单点故障(一个 Master 故障后,另一个可接管写入)。

(1)Master1 配置(my.cnf
1
2
3
4
5
6
[mysqld]
server-id=1
log-bin=master1_bin
log-slave-updates=1 # 允许从库将同步的变更写入自身 binlog(关键)
auto-increment-increment=2 # 自增步长(避免双主自增 ID 冲突)
auto-increment-offset=1 # 自增起始值(Master1 用 1,3,5...)
(2)Master2 配置(my.cnf
1
2
3
4
5
6
[mysqld]
server-id=2
log-bin=master2_bin
log-slave-updates=1
auto-increment-increment=2
auto-increment-offset=2 # 自增起始值(Master2 用 2,4,6...)
(3)互为主从配置
  • Master1 作为 Slave 连接 Master2,Master2 作为 Slave 连接 Master1(步骤同 “一主一从”)。
  • 关键:通过 auto-increment-incrementauto-increment-offset 避免双主自增 ID 冲突。

3. 级联复制(减轻 Master 压力)

当读压力极大时,Master 复制给少量 “中继 Slave”,再由中继 Slave 复制给其他 Slave,减少 Master 的 I/O 负担。

(1)中继 Slave 配置
  • 启用 log-slave-updates=1(允许将同步的变更写入自身 binlog)。
  • 表存储引擎改为 BLACKHOLE(黑洞引擎,仅记录 binlog 不存储数据,节省空间)。
(2)二级 Slave 配置
  • 以中继 Slave 为 Master 进行配置(步骤同 “一主一从”)。

主从一致性检验与问题排查

1. 一致性检验工具

  • pt-table-checksum:Percona 工具,对比主从表数据一致性,生成校验和报告。
  • mysqldiff:对比表结构差异。
  • checksum:对表计算校验和,手动对比主从结果。

2. 常见问题与解决

  • Slave_IO_Running=Connecting
    原因:网络不通、复制用户密码错误、Master 防火墙拦截。
    解决:检查 MASTER_HOSTMASTER_USERMASTER_PASSWORD,测试网络连通性。
  • Slave_SQL_Running=No
    原因:SQL 线程执行失败(如主键冲突、表不存在)。
    解决:查看 Last_SQL_Error,修复数据冲突后执行 START SLAVE SQL_THREAD;
  • 主从延迟(Seconds_Behind_Master 过大)
    原因:Slave 性能不足、大事务阻塞、网络延迟。
    解决:升级 Slave 硬件、拆分大事务、使用半同步复制

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10