MySQL 主从复制完整配置指南
MySQL 主从复制完整配置指南
在企业级应用中,单台 MySQL 数据库面临数据丢失风险高、高并发下性能不足等问题。MySQL 主从复制通过「主库写、从库读」的架构,可实现实时灾备、读写分离与数据备份,是解决上述问题的核心方案。本文基于文档内容,详细拆解主从复制的原理、配置步骤与验证方法,并补充关键注意事项与扩展说明,确保架构稳定可用。
一、MySQL 主从复制基础认知
1. 为何需要主从复制?
单台 MySQL 数据库存在两大核心隐患,主从复制正是针对这些问题设计:
- 数据安全风险:单库宕机(如硬件故障、误操作)可能导致数据永久丢失,主从复制可通过从库实现实时灾备,故障时快速切换。
- 性能瓶颈问题:业务增长后,读请求(如查询)占比极高,单库无法承载高并发,主从复制可将读请求分流到从库,提升整体服务质量。
2. 主从复制的核心作用
作用分类 | 具体说明 |
---|---|
实时灾备 | 从库实时同步主库数据,主库故障时,从库可立即切换为新主库,避免业务中断与数据丢失。 |
读写分离 | 主库仅处理写操作(插入、更新、删除),从库处理读操作(查询),分散单库压力,提升并发能力。 |
数据备份 | 从库可作为备份源,进行全量/增量备份,避免直接在主库备份占用资源,影响业务运行。 |
3. 主从复制的常见形式
根据业务需求,主从复制可灵活部署为以下架构:
- 一主一从:最基础架构,1 台主库 + 1 台从库,适用于中小业务的灾备与简单读写分离。
- 主主复制:2 台服务器互为主从,均可读写,适用于需双向同步数据的场景(如跨地域业务),但需注意冲突处理。
- 一主多从:1 台主库 + 多台从库,可进一步扩展读性能(如 3 台从库分别承载不同业务的读请求),是高并发读场景的主流选择。
- 多主一从:MySQL 5.7 及以上支持,多台主库数据同步到 1 台从库,适用于数据汇总场景(如多分支业务数据统一分析)。
- 联级复制:从库作为「中间主库」,再同步给下一级从库(主库 → 从库1 → 从库2),减少主库的 I/O 压力,适用于从库数量极多的场景。
二、MySQL 主从复制原理(核心机制)
主从复制基于「日志同步 + 线程协作」实现,核心涉及 3 个关键线程与 2 类日志,具体流程如下:
-
主库生成 binlog 日志与 log dump 线程
主库将所有写操作(INSERT/UPDATE/DELETE)记录到二进制日志(binlog)中,确保操作可追溯。同时,主库启动log dump
线程,负责监听 binlog 日志的变化,并将新日志发送给从库的 I/O 线程。 -
从库 I/O 线程接收日志并写入中继日志
从库启动I/O 线程
,主动连接主库的 log dump 线程,请求获取 binlog 日志。I/O 线程将接收到的 binlog 日志写入从库本地的「中继日志(relay log)」,避免直接解析日志导致业务延迟。 -
从库 SQL 线程解析中继日志并执行
从库启动SQL 线程
,实时读取中继日志中的内容,将其解析为与主库一致的 SQL 操作,并在从库中执行。最终实现主从库的数据一致性。
总结:主库通过 binlog 记录操作,从库通过 I/O 线程拉取日志、SQL 线程执行操作,三者协作完成「主写从读、数据同步」的核心目标。
三、MySQL 主从复制配置实战(一主一从)
1. 环境准备与需求说明
本次配置为「一主一从」架构,主库负责写操作,从库负责读操作,环境信息如下:
数据库角色 | IP 地址 | 操作系统 | MySQL 版本 | 初始数据状态 | 核心职责 |
---|---|---|---|---|---|
主数据库 | 172.16.12.128 | CentOS 7 | MySQL 5.7 | 有数据(含 student、teacher 库) | 处理写操作,生成 binlog |
从数据库 | 172.16.12.129 | CentOS 7 | MySQL 5.7 | 无业务数据(仅系统库) | 同步主库数据,处理读操作 |
前置条件:
- 两台服务器已安装 MySQL 5.7(安装步骤可参考前文「MySQL 多实例部署」中的软件下载、解压、权限配置流程)。
- 主从服务器之间网络互通(可通过
ping 172.16.12.129
验证),且防火墙开放 3306 端口(MySQL 默认端口):# 主从服务器均执行,开放 3306 端口并重启防火墙 [root@localhost ~]# firewall-cmd --zone=public --add-port=3306/tcp --permanent [root@localhost ~]# firewall-cmd --reload
2. 配置步骤详解(6 步完成)
步骤 1:确保主从库数据一致(全量备份与还原)
主从复制的前提是「初始数据完全一致」,否则后续同步会出现数据偏差。需先对主库进行全量备份,再将备份文件还原到从库:
1.1 主库锁表与全量备份
为避免备份期间主库有新写操作导致数据不一致,需先给主库加「读锁」,再执行备份:
# 1. 登录主库,执行读锁(此终端需保持打开,备份完成后再退出)
[root@localhost ~]# mysql -uroot -predhat
mysql> FLUSH TABLES WITH READ LOCK; # 锁定所有表,仅允许读操作
Query OK, 0 rows affected (0.00 sec)# 2. 新开一个终端,执行全量备份(--all-databases 备份所有库,含系统库与业务库)
[root@localhost ~]# mysqldump -uroot -predhat --all-databases > /opt/all-202408050937.sql
# 提示 “Using a password on the command line interface can be insecure.” 为正常警告# 3. 查看备份文件是否生成
[root@localhost ~]# ls /opt/
all-202408050937.sql # 备份文件存在,备份成功
1.2 备份文件传输到从库
通过 scp
命令将主库的备份文件传输到从库的 /opt/
目录:
# 主库终端执行,将备份文件传给从库(需输入从库 root 密码)
[root@localhost ~]# scp /opt/all-202408050937.sql root@172.16.12.129:/opt/
root@172.16.12.129's password: # 输入从库 root 密码
all-202408050937.sql 100% 786KB 10.6MB/s 00:00 # 传输完成
1.3 主库解锁表
备份文件传输完成后,回到主库的读锁终端,退出 MySQL 以解除锁表(若不解锁,主库将无法执行写操作):
mysql> quit # 退出主库,自动解除读锁
Bye
1.4 从库还原备份数据
在从库终端,执行备份文件还原,确保从库数据与主库一致:
# 从库执行还原命令(将备份文件导入 MySQL)
[root@localhost ~]# mysql -uroot -predhat < /opt/all-202408050937.sql# 验证还原结果:查看从库数据库列表,应与主库一致(含 student、teacher 库)
[root@localhost ~]# mysql -uroot -predhat -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| student | # 业务库,主库同步过来
| sys |
| teacher | # 业务库,主库同步过来
+--------------------+
步骤 2:主库创建同步账号并授权
从库需通过专用账号连接主库获取 binlog 日志,因此需在主库创建一个仅用于「主从同步」的账号(如 repl
),并授予 REPLICATION SLAVE
权限:
# 登录主库
[root@localhost ~]# mysql -uroot -predhat# 1. 创建同步账号 repl,允许从库(172.16.12.129)连接,密码为 redhat
mysql> CREATE USER 'repl'@'172.16.12.129' IDENTIFIED BY 'redhat';
Query OK, 0 rows affected (0.00 sec)# 2. 授予 repl 账号同步权限(REPLICATION SLAVE 权限仅用于主从同步,无其他权限)
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.16.12.129';
Query OK, 0 rows affected (0.00 sec)# 3. 刷新权限,使配置生效
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)# (可选)验证账号权限:查看 repl 账号的权限列表
mysql> SHOW GRANTS FOR 'repl'@'172.16.12.129';
+---------------------------------------------------+
| Grants for repl@172.16.12.129 |
+---------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.16.12.129' |
+---------------------------------------------------+
步骤 3:配置主库(启用 binlog 与唯一标识)
主库需启用二进制日志(binlog),并设置唯一的 server-id
(主库 server-id
必须小于从库,避免冲突),配置文件为 /etc/my.cnf
:
# 编辑主库配置文件
[root@localhost ~]# vim /etc/my.cnf# 在 [mysqld] 段落中添加以下配置(原有配置保留,新增关键参数)
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-bin=mysql-bin # 启用 binlog 日志,日志文件前缀为 mysql-bin(如 mysql-bin.000001)
server-id=1 # 主库唯一标识,取值范围 1-4294967295,必须与从库不同且更小
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid# 重启 MySQL 服务,使配置生效
[root@localhost ~]# systemctl restart mysqld# 验证主库是否启动成功(查看 3306 端口是否监听)
[root@localhost ~]# ss -antl
LISTEN 0 80 :::3306 :::* # 3306 端口监听,启动成功# 查看主库 binlog 状态(记录 log 文件名称与 Position 值,后续从库配置需用到)
[root@localhost ~]# mysql -uroot -predhat
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
# 关键信息:File=mysql-bin.000001,Position=154(从库需指定这两个值同步)
步骤 4:配置从库(启用中继日志与唯一标识)
从库需设置唯一的 server-id
(大于主库),并启用中继日志(relay log),配置文件同样为 /etc/my.cnf
:
# 编辑从库配置文件
[root@localhost ~]# vim /etc/my.cnf# 在 [mysqld] 段落中添加以下配置(原有配置保留,新增关键参数)
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server-id=2 # 从库唯一标识,必须大于主库的 server-id(主库为 1,此处设为 2)
relay-log=mysql-relay-bin # 启用中继日志,日志文件前缀为 mysql-relay-bin
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid# 重启 MySQL 服务,使配置生效
[root@localhost ~]# systemctl restart mysqld# 验证从库是否启动成功(查看 3306 端口监听)
[root@localhost ~]# ss -antl
LISTEN 0 80 :::3306 :::* # 启动成功
步骤 5:从库关联主库并启动同步
从库需通过 CHANGE MASTER TO
命令关联主库信息(主库 IP、同步账号、binlog 文件名与 Position 值),再启动同步线程:
# 登录从库
[root@localhost ~]# mysql -uroot -predhat# 1. 配置主库信息(替换为实际主库参数,Position 与 File 需与主库 SHOW MASTER STATUS 结果一致)
mysql> CHANGE MASTER TO-> MASTER_HOST='172.16.12.128', # 主库 IP 地址-> MASTER_USER='repl', # 主库创建的同步账号-> MASTER_PASSWORD='redhat', # 同步账号密码-> MASTER_LOG_FILE='mysql-bin.000001', # 主库 binlog 文件名(来自 SHOW MASTER STATUS)-> MASTER_LOG_POS=154; # 主库 binlog 位置(来自 SHOW MASTER STATUS)
Query OK, 0 rows affected, 2 warnings (0.33 sec)# 2. 启动从库同步线程(I/O 线程与 SQL 线程)
mysql> START SLAVE;
Query OK, 0 rows affected (0.01 sec)# 3. 查看从库同步状态(核心验证步骤,需确保 Slave_IO_Running 与 Slave_SQL_Running 均为 Yes)
mysql> SHOW SLAVE STATUS \G # \G 表示纵向显示结果,更易读
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send event # I/O 线程状态:等待主库发送日志Master_Host: 172.16.12.128 # 主库 IP 正确Master_User: repl # 同步账号正确Master_Port: 3306 # 主库端口正确Connect_Retry: 60 # 连接失败重试间隔(秒)Master_Log_File: mysql-bin.000001 # 主库 binlog 文件名正确Read_Master_Log_Pos: 154 # 主库 binlog 位置正确Relay_Log_File: mysql-relay-bin.000002 # 中继日志文件名Relay_Log_Pos: 320 # 中继日志位置Relay_Master_Log_File: mysql-bin.000001 # 关联的主库 binlog 文件名Slave_IO_Running: Yes # ✅ I/O 线程运行正常(必须为 Yes)Slave_SQL_Running: Yes # ✅ SQL 线程运行正常(必须为 Yes)Replicate_Do_DB: # 需同步的数据库(默认所有库)Replicate_Ignore_DB: # 忽略同步的数据库(默认无)
常见问题排查:
- 若
Slave_IO_Running: No
:检查主从网络是否互通、同步账号密码是否正确、主库 binlog 文件名/Position 是否正确。 - 若
Slave_SQL_Running: No
:检查主从初始数据是否一致(如备份还原是否成功)、从库是否有未同步的 SQL 冲突(可通过relay_log_recovery=1
配置自动恢复中继日志)。
步骤 6:测试主从同步效果
通过在主库执行写操作,验证从库是否能实时同步数据,确保架构生效:
6.1 主库执行写操作(插入数据)
# 登录主库,切换到 student 库,向 bj2 表插入数据
[root@localhost ~]# mysql -uroot -predhat
mysql> USE student;
Database changed# 查看 bj2 表初始状态(为空)
mysql> SELECT * FROM bj2;
Empty set (0.00 sec)# 插入 3 条测试数据
mysql> INSERT INTO bj2 VALUES (1,'sean',20),(2,'tom',23),(3,'jerry',30);
Query OK, 3 rows affected (0.00 sec)# 验证主库数据插入成功
mysql> SELECT * FROM bj2;
+----+-------+------+
| id | name | age |
+----+-------+------+
| 1 | sean | 20 |
| 2 | tom | 23 |
| 3 | jerry | 30 |
+----+-------+------+
6.2 从库验证数据同步
# 登录从库,切换到 student 库,查看 bj2 表数据
[root@localhost ~]# mysql -uroot -predhat
mysql> USE student;
Database changed# 查看 bj2 表数据(应与主库完全一致,说明同步成功)
mysql> SELECT * FROM bj2;
+----+-------+------+
| id | name | age |
+----+-------+------+
| 1 | sean | 20 |
| 2 | tom | 23 |
| 3 | jerry | 30 |
+----+-------+------+
四、主从复制进阶配置与注意事项
1. 读写分离实现(扩展)
主从复制仅完成数据同步,需通过「应用层配置」或「中间件」实现读写分离:
- 应用层配置:在代码中判断 SQL 类型,写操作(INSERT/UPDATE/DELETE)路由到主库,读操作(SELECT)路由到从库(如 Java 中通过 MyBatis 拦截器实现)。
- 中间件方案:使用 MySQL 中间件(如 MyCat、ProxySQL)统一管理主从地址,中间件自动实现读写分离,应用只需连接中间件地址,无需修改代码,适用于复杂架构。
2. 主从延迟优化(关键问题解决)
主从复制存在「延迟」(从库数据比主库晚几秒到几分钟),主要原因与优化方案如下:
延迟原因 | 优化方案 |
---|---|
从库 SQL 线程执行慢 | 1. 从库使用更高配置的 CPU(SQL 线程为单线程,CPU 性能影响大);2. 避免在主库执行大事务(如批量更新),拆分为小事务。 |
主库 binlog 传输慢 | 1. 主从使用内网高速网络(如万兆网卡);2. 主库启用 binlog_group_commit (MySQL 5.7+ 特性,批量提交 binlog,减少 I/O 次数)。 |
从库中继日志堆积 | 1. 从库启用 relay_log_info_repository=TABLE (将中继日志信息存入表,避免文件 I/O 瓶颈);2. 定期清理过期中继日志(通过 expire_logs_days 配置日志保留天数)。 |
3. 主库故障切换(灾备实战)
当主库宕机时,需将从库切换为新主库,步骤如下:
- 确认主库故障:通过
ping
、telnet 172.16.12.128 3306
验证主库是否不可用。 - 停止从库同步:在从库执行
STOP SLAVE;
,避免主库恢复后数据冲突。 - 从库提升为主库:在从库执行
RESET MASTER;
,生成新的 binlog 日志,从库变为新主库。 - 应用切换地址:将应用的数据库地址从原主库(172.16.12.128)改为新主库(172.16.12.129)。
- 原主库恢复后处理:原主库修复后,配置为新主库的从库(执行
CHANGE MASTER TO
关联新主库),实现新的主从架构。
4. 安全加固建议
- 同步账号权限最小化:仅授予
REPLICATION SLAVE
权限,避免授予ALL PRIVILEGES
等高危权限。 - binlog 日志加密:MySQL 8.0+ 支持 binlog 加密(
binlog_encryption=ON
),防止日志被篡改或窃取。 - 定期备份从库:从库作为灾备源,需定期执行全量备份(如每天一次),并测试备份文件的可用性。
- 禁用符号链接:配置文件中
symbolic-links=0
,避免通过符号链接篡改数据文件。
五、总结
MySQL 主从复制是企业级数据库架构的基础,通过「主写从读、数据同步」解决了单库的数据安全与性能问题。本文基于 CentOS 7 + MySQL 5.7 环境,详细讲解了一主一从架构的配置流程,核心步骤可概括为「数据一致 → 账号授权 → 主库配置 → 从库关联 → 同步验证」。在实际应用中,需结合业务需求选择合适的主从形式,并通过读写分离、延迟优化、故障切换等进阶配置,确保架构稳定、高效、可靠。