MySQL 主从复制搭建全流程笔记(AI润色)
在生产环境中,单节点 MySQL 存在单点故障、读写压力瓶颈、数据容灾不足等问题,而主从复制✅读写分离:主库负责写操作,从库负责读操作,分摊业务压力✅数据容灾:从库实时同步主库数据,主库故障时可快速切换✅数据备份:在从库执行备份操作,不影响主库业务✅高可用架构:基于主从搭建 MHA、Keepalived 等高可用方案时间同步:主从必须用 NTP 同步时间,否则会出现各种诡异问题server-id
一、前言:为什么要做 MySQL 主从复制?
在生产环境中,单节点 MySQL 存在单点故障、读写压力瓶颈、数据容灾不足等问题,而主从复制是解决这些问题的基础方案:
- ✅ 读写分离:主库负责写操作,从库负责读操作,分摊业务压力
- ✅ 数据容灾:从库实时同步主库数据,主库故障时可快速切换
- ✅ 数据备份:在从库执行备份操作,不影响主库业务
- ✅ 高可用架构:基于主从搭建 MHA、Keepalived 等高可用方案
二、MySQL 主从复制核心原理
先上原理图,直观理解整个流程:

核心流程(4 步实现数据同步)
- 主库写日志:主库开启二进制日志(
Binary log),所有数据更新(增删改、DDL)都会写入 binlog - 从库拉取日志:从库的I/O 线程主动连接主库,请求拉取主库的 binlog
- 从库存日志:从库 I/O 线程将拉取到的日志写入本地中继日志(Relay log)
- 从库重放日志:从库的SQL 线程读取 Relay log,重放其中的 SQL 操作,最终实现主从数据一致
关键组件说明
表格
| 组件 | 作用 |
|---|---|
| Binary log(二进制日志) | 主库记录所有写操作的日志,是主从复制的基础 |
| Relay log(中继日志) | 从库暂存主库传来的 binlog,避免主库压力过大 |
| I/O 线程 | 从库负责拉取主库 binlog 的线程 |
| SQL 线程 | 从库负责重放 Relay log 的线程 |
| Dump 线程 | 主库负责发送 binlog 给从库的线程(原理图未画出,实际存在) |
三、实验环境准备(主从节点都要执行)
环境说明
- 系统:CentOS 7/8 或 openEuler(Linux 通用)
- MySQL 版本:5.7/8.0(本次实验兼容 8.0,处理了密码插件兼容问题)
- 主库 IP:
192.168.166.230,从库 IP:192.168.166.x(同网段)
3.1 网络时间同步(chrony)
主从时间必须严格同步,否则会导致 binlog 时间戳异常、复制失败!
# 1. 编辑chrony配置,添加阿里云NTP源(保证时间准确)
[root@localhost ~]# cat /etc/chrony.conf | grep -Ev '^$|#'
server ntp.aliyun.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
# 2. 设置时区为上海(避免时区差)
[root@localhost ~]# timedatectl set-timezone Asia/Shanghai
# 3. 重启chrony服务,设置开机自启
[root@localhost ~]# systemctl restart chronyd.service
[root@localhost ~]# systemctl enable chronyd.service
# 验证时间同步(可选)
[root@localhost ~]# chronyc sources -v
[root@localhost ~]# timedatectl
3.2 关闭防火墙与 SELinux
实验环境直接关闭,避免端口拦截、权限问题;生产环境可仅开放 3306 端口
# 1. 关闭防火墙,禁用开机自启
[root@localhost ~]# systemctl disable --now firewalld
# 2. 永久关闭SELinux(修改配置文件,重启生效)
[root@localhost ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 3. 临时关闭SELinux(当前系统立即生效)
[root@localhost ~]# setenforce 0
# 验证SELinux状态(显示Permissive/Disabled即为成功)
[root@localhost ~]# getenforce
四、主从复制详细配置
4.1 主库(Master)配置
4.1.1 修改 MySQL 配置文件 /etc/my.cnf
[mysqld]
# 开启二进制日志,文件名前缀为mysql-bin(必须配置)
log-bin=mysql-bin
# 二进制日志格式:statement(基于SQL语句),生产环境推荐row(基于行)
binlog_format="statement"
# 服务器唯一ID,主从必须不同,主库设为11(自定义,1-2^32-1之间)
server-id=11
# 开启从库更新日志(级联复制时需要,即从库作为其他节点的主库)
log-slave-updates=true
[client-server]
# 加载/etc/my.cnf.d目录下的所有配置文件
!includedir /etc/my.cnf.d
⚠️ 关键注意:server-id必须全局唯一,主从不能相同,否则复制直接失败!
4.1.2 重启 MySQL 服务,验证 binlog 生成
# 启动MySQL,设置开机自启
[root@localhost ~]# systemctl enable --now mysqld
# 进入MySQL数据目录,查看binlog文件
[root@localhost ~]# cd /var/lib/mysql/
[root@localhost mysql]# ls
如果看到 mysql-bin.000001、mysql-bin.index 这类文件,说明 binlog 开启成功。
4.1.3 创建复制专用用户,授权
-- 进入MySQL命令行
[root@localhost mysql]# mysql
-- 1. 创建从库访问用户,允许192.168.166.%网段访问
mysql> create user slave@'192.168.166.%' identified by '123.com';
-- 2. 授权(⚠️ 生产环境绝对不要用all on *.*,最小权限原则:replication slave)
mysql> grant replication slave on *.* to 'slave'@'192.168.166.%';
-- 实验环境为了方便用all,生产环境务必用最小权限!
-- 3. 修改密码插件为mysql_native_password(MySQL8.0+默认是caching_sha2_password,从库可能不兼容)
mysql> ALTER USER 'slave'@'192.168.166.%' IDENTIFIED WITH mysql_native_password BY '123.com';
-- 4. 刷新权限
mysql> flush privileges;
4.1.4 查看主库 binlog 状态,记录关键信息
mysql> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| mysql-bin.000005 | 2567 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
⚠️ 超级重要:记录完 File(mysql-bin.000005) 和 Position(2567) 后,绝对不要在主库执行任何写操作(insert/update/delete/create/drop 等),否则 Position 会变化,导致从库同步失败!
4.2 从库(Slave)配置
4.2.1 修改 MySQL 配置文件 /etc/my.cnf
[mysqld]
# 中继日志索引文件(必须配置,用于管理relay log)
relay-log-index=slave-bin.index
# 服务器唯一ID,必须和主库不同,从库设为22
server-id=22
[client-server]
!includedir /etc/my.cnf.d
4.2.2 重启 MySQL 服务,验证初始状态
# 启动MySQL,设置开机自启
[root@localhost ~]# systemctl enable --now mysqld
# 查看数据目录,此时还没有relay log(未连接主库,属于正常现象)
[root@localhost ~]# cd /var/lib/mysql/
[root@localhost mysql]# ls
4.2.3 配置从库连接主库,开启复制
-- 进入MySQL命令行
[root@localhost mysql]# mysql
-- 配置主库信息(必须和主库show master status的结果完全一致!)
mysql> change master to
master_host='192.168.166.230', -- 主库IP(绝对不能写错!)
master_user='slave', -- 主库创建的复制用户
master_password='123.com', -- 复制用户密码
master_port=3306, -- MySQL端口,默认3306
master_log_file='mysql-bin.000005', -- 主库show master status的File
master_log_pos=2567; -- 主库show master status的Position
-- 启动从库复制角色
mysql> start slave;
4.2.4 验证从库复制状态(核心!)
mysql> show slave status\G;
重点看 3 个关键状态,全部正常才说明主从搭建成功:
Slave_IO_Running: Yes -- I/O线程正常,成功连接主库拉取binlog
Slave_SQL_Running: Yes -- SQL线程正常,成功重放relay log
Seconds_Behind_Master: 0 -- 主从延迟为0,同步实时
同时查看数据目录,会生成 slave-bin.000001、slave-bin.index等中继日志文件,说明 I/O 线程已经正常拉取主库 binlog。
五、常见问题排查(踩坑记录)
5.1 高频异常:Slave_IO_Running 为 Connecting,无法连接主库
异常现象
Slave_IO_State: Connecting to source
Slave_IO_Running: Connecting
Last_IO_Errno: 2003
Last_IO_Error: Error connecting to source 'slave@192.168.166.230:3306'. Message: Can't connect to MySQL server on '192.168.166.230:3306' (113)
问题原因(按概率排序)
- 主库 IP 写错:最常见!比如
change master to里的master_host填错(本次实验原始配置中就出现了 192.168.158.4 的笔误) - 网络不通:主从防火墙未关闭,3306 端口被拦截
- 复制用户权限问题:用户的
host不允许从库 IP 访问,或密码错误 - 主库 MySQL 未启动:主库服务挂了,无法响应连接
排查 & 解决方法
- 检查主库 IP:从库执行
ping 192.168.166.230,确认网络可达 - 检查 3306 端口:从库执行
telnet 192.168.166.230 3306,不通则关闭防火墙 / 开放端口 - 检查复制用户:主库执行
select user,host from mysql.user;,确认slave用户的host为192.168.166.% - 纠正配置:重新执行
change master to,然后stop slave; start slave;重启复制
5.2 其他常见问题补充
表格
| 异常现象 | 原因 | 解决方法 |
|---|---|---|
| Slave_SQL_Running 为 No | 主从数据不一致(从库执行了写操作、表结构不一致) | 生产环境修复数据;测试环境可stop slave; set global sql_slave_skip_counter=1; start slave;跳过错误 |
| Seconds_Behind_Master 持续增大 | 主库写压力大、从库性能不足、网络延迟高 | 优化主库写操作、升级从库硬件、开启并行复制 |
| 主从数据不一致 | binlog 格式为 statement,SQL 在主从执行结果不同 | 生产环境将 binlog_format 改为row,基于行复制避免逻辑问题 |
六、总结与生产环境优化建议
核心注意事项
- 时间同步:主从必须用 NTP 同步时间,否则会出现各种诡异问题
- server-id 唯一:主从、级联复制的所有节点
server-id必须全局唯一 - 权限最小化:复制用户仅授予
replication slave权限,禁止all on *.* - binlog 格式:生产环境推荐
row格式,避免 statement 格式的逻辑不一致
生产环境优化方向
- ✅ GTID 复制:替代传统基于位置的复制,不用手动指定
master_log_file和master_log_pos,运维更简单 - ✅ 并行复制:开启从库多线程并行重放 relay log,大幅降低主从延迟
- ✅ 读写分离中间件:基于主从搭建 MyCat、Sharding-JDBC 等中间件,实现自动读写分离
- ✅ 监控告警:监控
Slave_IO_Running、Slave_SQL_Running、Seconds_Behind_Master,异常及时告警
更多推荐


所有评论(0)