MySQL主从复制 - 指南
在数据库主从复制(以 MySQL 为例)的语境中,“两日志” 和 “三进程” 是保障数据同步的核心组件,分别对应日志文件和同步进程,共同实现主库数据到从库的一致性复制。
一、两日志:主从复制的 “数据载体”
“两日志” 指主库的二进制日志(binlog) 和从库的中继日志(relay log),它们是数据同步的 “桥梁”,负责记录和传递写操作。
1. 二进制日志(Binary Log,简称 binlog)
- 位置:主库服务器(
/var/lib/mysql/mysql-bin.xxxxxx
,路径可通过my.cnf
的log-bin
配置)。 - 作用:记录主库上所有写操作(INSERT/UPDATE/DELETE/DDL 等),以二进制格式存储,是主从复制的 “源头”。
- 特点:
- 按时间顺序记录,每个操作包含 “事件类型”“数据变更”“发生时间” 等信息;
- 可通过
binlog_format
配置记录格式(ROW 格式记录行级变更,最常用,兼容性好); - 主库必须开启 binlog(
log-bin=mysql-bin
)才能进行主从复制。
2. 中继日志(Relay Log)
- 位置:从库服务器(
/var/lib/mysql/mysql-relay-bin.xxxxxx
,路径可通过my.cnf
的relay-log
配置)。 - 作用:从库的 IO 线程读取主库的 binlog 后,先写入本地中继日志,再由 SQL 线程从中继日志中读取并执行操作,相当于 “中间缓冲区”。
- 特点:
- 格式与 binlog 完全一致(可理解为 “从库本地的 binlog 副本”);
- 避免从库直接依赖主库的 binlog(主库 binlog 可能被删除或轮转,中继日志确保从库有独立的同步源);
- 同步完成后,旧的中继日志会被自动清理(由
relay_log_purge
控制,默认开启)。
二、三进程:主从复制的 “执行单元”
“三进程” 指主库的dump 线程和从库的IO 线程、SQL 线程,三者协同完成 “主库写操作→从库同步” 的全流程。
1. 主库:dump 线程(Binlog Dump Thread)
- 作用:当从库连接主库请求同步时,主库创建 dump 线程,负责将 binlog 中的内容发送给从库。
- 工作流程:
- 从库的 IO 线程连接主库时,主库启动 dump 线程;
- dump 线程根据从库指定的 binlog 文件名和位置(
MASTER_LOG_FILE
和MASTER_LOG_POS
),读取主库 binlog 中的事件; - 将读取到的 binlog 事件逐发给从库的 IO 线程。
2. 从库:IO 线程(I/O Thread)
- 作用:连接主库,接收主库 dump 线程发送的 binlog 事件,并写入从库的中继日志。
- 工作流程:
- 从库执行
START SLAVE
后,IO 线程启动,连接主库(使用主库配置的同步账号); - 向主库请求从指定 binlog 位置开始的事件;
- 接收主库 dump 线程发送的 binlog 事件,按顺序写入从库的中继日志;
- 同时记录当前同步到的 binlog 位置(更新
master.info
文件,用于故障重启后继续同步)。
- 从库执行
3. 从库:SQL 线程(SQL Thread)
- 作用:读取中继日志中的 binlog 事件,在从库中 “重放” 这些操作,最终实现数据同步。
- 工作流程:
- 从库启动后,SQL 线程启动,读取中继日志(
relay-log.info
记录当前读取位置); - 解析中继日志中的 binlog 事件,将其转换为具体的 SQL 操作(如 INSERT/UPDATE);
- 在从库中执行这些 SQL 操作,使从库数据与主库保持一致。
- 从库启动后,SQL 线程启动,读取中继日志(
三、两日志与三进程的协同流程
主从复制的完整链路是 “日志” 与 “进程” 的紧密配合,步骤如下:
- 主库执行写操作,自动记录到binlog;
- 从库的IO 线程连接主库,主库启动dump 线程;
- dump 线程读取主库 binlog 中的事件,发送给从库 IO 线程;
- 从库 IO 线程将接收的事件写入中继日志;
- 从库的SQL 线程读取中继日志,重放事件到从库数据文件。
两日志(binlog + relay log)是数据同步的 “载体”,负责记录和暂存写操作;
三进程(dump 线程 + IO 线程 + SQL 线程)是数据同步的 “执行者”,负责在主从库之间传递和执行操作。
主从复制是数据库高可用架构的基础技术,通过将主库的写操作同步到从库,实现数据冗余、读写分离和故障转移。以下从核心原理、实现步骤、同步模式、常见问题四个维度详细讲解(以 MySQL 为例):
一、主从复制的核心原理
主从复制本质是 **“主库写操作记录→从库获取并执行”** 的过程,依赖三个关键机制:
- 日志记录:主库将所有写操作(INSERT/UPDATE/DELETE/DDL)记录到二进制日志(binlog)。
- 日志传输:从库主动获取主库的 binlog,并存储为中继日志(relay log)。
- 日志重放:从库读取中继日志,重新执行其中的操作,实现数据同步。
核心组件(两日志三进程):
- 二进制日志(binlog):主库产生,记录所有写操作,是同步的 “数据源”。
- 中继日志(relay log):从库存储,临时保存主库的 binlog 内容,是同步的 “中转站”。
- Dump 线程:主库进程,负责向从库发送 binlog 内容。
- IO 线程:从库进程,负责接收主库的 binlog 并写入中继日志。
- SQL 线程:从库进程,负责读取中继日志并执行其中的操作。
二、主从复制的实现步骤(MySQL 5.7/8.0)
1. 环境准备
- 服务器规划:
- 主库(Master):192.168.1.100,MySQL 5.7+
- 从库(Slave):192.168.1.101,MySQL 5.7+(版本需 ≥ 主库)
- 基础配置:
- 关闭防火墙(或开放 3306 端口)。
- 主从库时间同步(
ntpdate
或 chrony),避免因时间差导致日志同步异常。 -
# 安装NTP服务 sudo apt-get install ntp # Debian/Ubuntu sudo yum install ntp # CentOS/RHEL # 启动并设置开机自启 sudo systemctl start ntpd sudo systemctl enable ntpd # 检查时间同步状态 ntpq -p
2. 主库配置(192.168.1.100)
(1)修改 MySQL 配置文件(my.cnf
或 mysqld.cnf
)
[mysqld]
# 1. 主库唯一标识(1-4294967295,从库需不同)
server-id = 100
# 2. 开启 binlog,指定日志文件名前缀
log-bin = mysql-bin
# 3. binlog 记录格式(推荐 ROW,记录行级变更,兼容性最好)
binlog_format = ROW
# 4. 同步的数据库(可选,不配置则同步所有库)
binlog-do-db = test_db
# 5. 忽略同步的数据库(如系统库)
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
# 6. 避免从库同步后再次生成 binlog(防止循环同步)
log-slave-updates = 0
(2)重启主库并验证配置
systemctl restart mysqld
# 登录 MySQL 验证 binlog 是否开启
mysql -u root -p
mysql> SHOW VARIABLES LIKE 'log_bin'; # 输出 Value: ON 即正常
mysql> SHOW MASTER STATUS; # 查看 binlog 状态(初始为空,需后续操作生成)
(3)创建主从同步专用账号
从库需通过该账号连接主库获取 binlog:
# 创建账号(用户名:repl_user,允许从库 IP 访问)
CREATE USER 'repl_user'@'192.168.1.101' IDENTIFIED BY 'Repl@123';
# 授予复制权限(仅需 REPLICATION SLAVE 权限)
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.101';
FLUSH PRIVILEGES;
3. 从库配置(192.168.1.101)
(1)修改 MySQL 配置文件
[mysqld]
# 1. 从库唯一标识(需与主库不同)
server-id = 101
# 2. 开启中继日志(存储主库的 binlog)
relay-log = mysql-relay-bin
# 3. 同步的数据库(与主库保持一致)
replicate-do-db = test_db
# 4. 忽略同步的数据库(与主库保持一致)
replicate-ignore-db = mysql
replicate-ignore-db = information_schema
# 5. 从库只读(禁止直接写从库,确保数据一致性)
read-only = 1
# 6. 允许超级用户临时写从库(可选,用于维护)
super-read-only = 0
(2)重启从库
systemctl restart mysqld
(3)配置从库关联主库
登录从库 MySQL,执行以下命令关联主库信息:
# 停止当前同步(若之前配置过)
STOP SLAVE;
# 重置从库状态(清除旧同步信息)
RESET SLAVE;
# 关联主库(替换为实际信息)
CHANGE MASTER TO
MASTER_HOST = '192.168.1.100', # 主库 IP
MASTER_USER = 'repl_user', # 同步账号
MASTER_PASSWORD = 'Repl@123', # 账号密码
MASTER_LOG_FILE = 'mysql-bin.000001', # 主库当前 binlog 文件名(从主库 SHOW MASTER STATUS 获取)
MASTER_LOG_POS = 154; # 主库当前 binlog 位置(从主库 SHOW MASTER STATUS 获取)
# 启动同步
START SLAVE;
4. 验证主从同步状态
在从库执行以下命令,关键参数需满足:
SHOW SLAVE STATUS\G; # \G 垂直显示结果
Slave_IO_Running: Yes
:IO 线程正常(从库能接收主库 binlog)。Slave_SQL_Running: Yes
:SQL 线程正常(从库能重放中继日志)。Seconds_Behind_Master: 0
:数据无延迟(正常状态)。
三、主从复制的同步模式
根据数据一致性和性能的平衡,主从复制有三种同步模式:
异步复制(默认模式)
- 原理:主库执行写操作后,立即返回结果给客户端,无需等待从库确认。
- 优点:性能最好,主库无延迟。
- 缺点:主库崩溃时,可能丢失未同步到从库的数据。
半同步复制(Semi-Sync)
- 原理:主库执行写操作后,需等待至少一个从库接收并写入中继日志,才返回结果给客户端。
- 优点:避免数据丢失(主库崩溃时,至少有一个从库有完整数据)。
- 缺点:主库需等待从库确认,性能略有下降(延迟取决于网络)。
- 启用方式:主从库均需安装半同步插件(
rpl_semi_sync_master
和rpl_semi_sync_slave
)。
全同步复制(Group Replication)
- 原理:主库执行写操作后,需等待所有从库执行完成并确认,才返回结果。
- 优点:数据零丢失,强一致性。
- 缺点:性能差(延迟随从库数量增加而增加),仅适合对一致性要求极高的场景(如金融核心库)。
四、常见问题与解决方案
Slave_IO_Running: Connecting
- 原因:主库 IP / 端口错误、同步账号密码错误、主库防火墙拦截。
- 解决:
- 测试从库到主库的网络:
telnet 192.168.1.100 3306
- 验证同步账号:
mysql -u repl_user -p'Repl@123' -h 192.168.1.100
- 测试从库到主库的网络:
Slave_SQL_Running: No
- 原因:从库执行中继日志时出错(如主键冲突、表结构不一致)。
- 解决:
- 查看错误日志:
tail -n 100 /var/log/mysqld.log
- 临时跳过错误:
SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;
- 根本解决:修复主从库数据 / 表结构一致性。
- 查看错误日志:
从库延迟(
Seconds_Behind_Master
增大)- 原因:主库写压力大、从库性能不足、网络延迟。
- 解决:
- 优化从库硬件(CPU / 内存 / IO);
- 减少从库非必要操作(如关闭从库 binlog);
- 增加从库数量,分担读压力。
总结
主从复制通过 “日志记录 - 传输 - 重放” 机制实现数据同步,是数据库高可用和读写分离的基础。实际应用中需根据业务需求选择同步模式(异步 / 半同步),并关注同步状态和延迟问题。掌握主从复制的配置和排错,是构建稳定数据库架构的核心技能。