Mysql集群实战--主从复制
MySQL Node1 (master) 配置

[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
# ===== 复制配置 =====
server-id=10
log-bin=mysql-bin
relay-log=mysql-relay-bin
relay-log-index=mysql-relay-bin.index
# ===== Slave优化 =====
master_info_repository=TABLE # 用表存储复制信息
relay_log_info_repository=TABLE
relay_log_recovery=ON # 自动恢复中继日志
# ===== 并行复制配置 (MySQL 8.0+) =====
slave_parallel_workers=4 # 根据CPU核数调整
slave_parallel_type=LOGICAL_CLOCK
slave_preserve_commit_order=ON
# ===== 网络配置 =====
slave_net_timeout=60
master_connect_retry=60
# ===== 可选:日志过滤 =====
# replicate-do-db=业务库名
# replicate-ignore-db=mysql,sys
# ===== 可选:半同步复制 =====
# rpl_semi_sync_slave_enabled=1
MySQL Node2 (Slave) 配置
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
# ===== 复制配置 =====
server-id=20
log-bin=mysql-bin
relay-log=mysql-relay-bin
relay-log-index=mysql-relay-bin.index
# ===== Slave优化 =====
master_info_repository=TABLE # 用表存储复制信息
relay_log_info_repository=TABLE
relay_log_recovery=ON # 自动恢复中继日志
# ===== 并行复制配置 (MySQL 8.0+) =====
slave_parallel_workers=4 # 根据CPU核数调整
slave_parallel_type=LOGICAL_CLOCK
slave_preserve_commit_order=ON
# ===== 网络配置 =====
slave_net_timeout=60
master_connect_retry=60
# ===== 可选:日志过滤 =====
# replicate-do-db=业务库名
# replicate-ignore-db=mysql,sys
# ===== 可选:半同步复制 =====
# rpl_semi_sync_slave_enabled=1
### 
### 1.5 重启所有MySQL服务
在两台主机中重启数据库
root@mysql-node1 \~# /etc/init.d/mysqld restart
root@mysql-node2 \~# /etc/init.d/mysqld restart
或使用systemctl
systemctl restart mysqld

### 2.建立同步时需要用到的数据库账号
### 2.1 在Master节点创建复制用户
root@mysql-node1 \~# mysql -uroot -proot
mysql: Warning Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.3.0 Source distribution
mysql> SHOW VARIABLES LIKE 'default_authentication_plugin';
±------------------------------±----------------------+
| Variable_name | Value |
±------------------------------±----------------------+
| default_authentication_plugin | caching_sha2_password |
±------------------------------±----------------------+
1 row in set (0.00 sec)
创建复制用户
注意:MySQL 8.0使用caching_sha2_password认证,复制需要使用mysql_native_password
mysql> CREATE USER 'swp'@'%' IDENTIFIED WITH mysql_native_password BY 'swp@123456';
Query OK, 0 rows affected (0.04 sec)
查看创建的用户
mysql> SELECT User FROM mysql.user;
±-----------------+
| User |
±-----------------+
| swp |
| mysql.infoschema |
| mysql.session |
| mysql.sys |
| root |
±-----------------+
5 rows in set (0.00 sec)

授予复制权限(最小权限原则)
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO 'swp'@'%';
Query OK, 0 rows affected (0.00 sec)
刷新权限
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
验证权限
mysql> SHOW GRANTS FOR 'swp'@'%';
±--------------------------------------------+
| Grants for swp@% |
±--------------------------------------------+
| GRANT REPLICATION SLAVE ON . TO swp@% |
±--------------------------------------------+
1 row in set (0.00 sec)

### 2.2 验证复制用户能否从Slave连接
砰
在Slave节点验证连接
root@mysql-node2 \~# mysql -uswp -p'swp' -h172.25.254.10
mysql: Warning Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.3.0 Source distribution
mysql> quit
Bye
连接成功表示网络和权限配置正确
# 第二部分:主从复制配置
## 3. 配置数据库一主一从
### 3.1 在Master节点查看二进制日志信息
砰
root@mysql-node1 \~# mysql -uroot -proot
查看Master状态
mysql> SHOW MASTER STATUS;
±-----------------±---------±-------------±-----------------±------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
±-----------------±---------±-------------±-----------------±------------------+
| mysql-bin.000001 | 659 | | | |
±-----------------±---------±-------------±-----------------±------------------+
1 row in set (0.00 sec)
说明:
File: 当前二进制日志文件名
Position: 日志文件中当前位置
这两个值在配置Slave时需要用到

### 3.2 方案一:基于二进制日志位置的复制(传统方式)
砰
root@mysql-node2 \~# mysql -uroot -proot
配置与Master的连接信息
mysql> CHANGE MASTER TO
MASTER_HOST='172.25.254.10',
MASTER_USER='swp',
MASTER_PASSWORD='swp',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=659;
Query OK, 0 rows affected, 8 warnings (0.03 sec)
启动Slave复制
mysql> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 172.25.254.10
Master_User: swp
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 659
Relay_Log_File: mysql-node2-relay-bin.000002
Relay_Log_Pos: 328
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes # ✓ 正常:IO线程运行中
Slave_SQL_Running: Yes # ✓ 正常:SQL线程运行中
Seconds_Behind_Master: 0 # ✓ 正常:复制延迟为0
Last_Error: # ✓ 正常:无错误
1 row in set (0.00 sec)

### 3.3 方案二:基于GTID的复制(推荐,MySQL 5.7+)
砰
首先在Master和Slave的my.cnf中添加GTID配置
mysqld
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
重启MySQL后,在Slave端执行:
root@mysql-node2 \~# mysql -uroot -proot
mysql> CHANGE MASTER TO
MASTER_HOST='172.25.254.10',
MASTER_USER='swp',
MASTER_PASSWORD='swp',
MASTER_AUTO_POSITION=1; # 使用GTID自动定位
Query OK, 0 rows affected (0.00 sec)
mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
GTID优势:
1. 自动定位,无需手动指定日志位置
2. 故障转移时更易处理
3. 可支持多源复制
### 3.4 复制状态关键参数说明
| 参数 | 说明 | 正常值 |
| ----------------------- | ---------------- | -------------- |
| `Slave_IO_State` | Slave IO线程状态 | 等待源发送事件 |
| `Slave_IO_Running` | IO线程是否运行 | 是的 |
| `Slave_SQL_Running` | SQL线程是否运行 | 是的 |
| `Seconds_Behind_Master` | 复制延迟 | 0 或接近0 |
| `Last_Error` | 最后错误信息 | 空 |
| `Relay_Log_Pos` | 中继日志位置 | 递增 |
### 3.5 Node2和Node3都作为Slave的配置
砰
Node3的配置类似Node2
root@mysql-node3 \~# mysql -uroot -proot
mysql> CHANGE MASTER TO
MASTER_HOST='172.25.254.10',
MASTER_USER='swp',
MASTER_PASSWORD='swp',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=659;
Query OK, 0 rows affected, 8 warnings (0.03 sec)
mysql> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.03 sec)
mysql> SHOW SLAVE STATUS\G;
验证两个Slave都处于正常复制状态
# 第三部分:功能验证
## 4. 测试主从复制
### 4.1 在Master上创建数据库

root@mysql-node1 \~# mysql -uroot -proot
mysql> SHOW DATABASES;
±-------------------+
| Database |
±-------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
±-------------------+
4 rows in set (0.00 sec)
创建测试数据库
mysql> CREATE DATABASE baibai;
Query OK, 1 row affected (0.00 sec)
mysql> SHOW DATABASES;
±-------------------+
| Database |
±-------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| baibai |
±-------------------+
5 rows in set (0.00 sec)

### 4.2 在Slave上验证数据库同步
砰
在Node2上验证
root@mysql-node2 \~# mysql -uroot -proot
mysql> SHOW DATABASES;
±-------------------+
| Database |
±-------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| biabai |
±-------------------+
5 rows in set (0.00 sec)
baiabi数据库已同步!
# Master上创建表
[root@mysql-node1 ~]# mysql -uroot -proot
mysql> USE timinglee;
Database changed
mysql> CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Query OK, 0 rows affected (0.05 sec)
# 插入测试数据
mysql> INSERT INTO users(name, email) VALUES ('Alice', 'alice@example.com');
mysql> INSERT INTO users(name, email) VALUES ('Bob', 'bob@example.com');
mysql> INSERT INTO users(name, email) VALUES ('Charlie', 'charlie@example.com');
Query OK, 3 rows affected (0.02 sec)
mysql> SELECT * FROM users;
+----+---------+----------------------+---------------------+
| id | name | email | created_at |
+----+---------+----------------------+---------------------+
| 1 | Alice | alice@example.com | 2026-04-10 19:45:00 |
| 2 | Bob | bob@example.com | 2026-04-10 19:45:01 |
| 3 | Charlie | charlie@example.com | 2026-04-10 19:45:02 |
+----+---------+----------------------+---------------------+
3 rows in set (0.00 sec)
4.4 Slave上验证数据同步
砰
# 在Node2上验证
[root@mysql-node2 ~]# mysql -uroot -proot
mysql> USE timinglee;
Database changed
mysql> SELECT * FROM users;
+----+---------+----------------------+---------------------+
| id | name | email | created_at |
+----+---------+----------------------+---------------------+
| 1 | Alice | alice@example.com | 2026-04-10 19:45:00 |
| 2 | Bob | bob@example.com | 2026-04-10 19:45:01 |
| 3 | Charlie | charlie@example.com | 2026-04-10 19:45:02 |
+----+---------+----------------------+---------------------+
3 rows in set (0.00 sec)
# 数据完全同步!
# 在Node3上也验证
[root@mysql-node3 ~]# mysql -uroot -proot
mysql> USE timinglee;
mysql> SELECT * FROM users;
# 同样的结果表示复制成功
4.5 完整的功能测试清单
砰
# 测试1:验证Master和Slave状态
mysql> SHOW MASTER STATUS; # Master日志信息
mysql> SHOW SLAVE HOSTS; # Master查看连接的Slave
mysql> SHOW SLAVE STATUS\G; # Slave查看复制状态
# 测试2:验证权限
mysql> SHOW GRANTS FOR 'swp'@'%'; # 确认复制权限
# 测试3:验证二进制日志
mysql> SHOW BINARY LOGS; # 查看日志文件
mysql> SHOW MASTER STATUS; # 查看当前日志位置
# 测试4:数据一致性检查
# Master: mysql> CHECKSUM TABLE timinglee.users;
# Slave: mysql> CHECKSUM TABLE timinglee.users;
# 确保校验和相同
# 测试5:压力测试
# 在Master上大量写入,检查Slave是否能跟上
# 监控 Seconds_Behind_Master
第四部分:实验优化优化配置
5. 配置优化
5.1 二进制日志优化
INI
# my.cnf - Master配置
[mysqld]
# ===== 日志格式选择 =====
# ROW: 记录行级变化(推荐,数据一致性最好)
# STATEMENT: 记录SQL语句(日志小,但可能不一致)
# MIXED: 混合模式(MySQL 5.7默认)
binlog_format=ROW
# ===== ROW格式优化 =====
binlog_row_image=MINIMAL # 只记录修改的列(更快,日志更小)
# binlog_row_image=FULL # 记录所有列(默认,最安全)
# ===== 日志过期和清理 =====
expire_logs_days=7 # 自动删除7天前的日志
# 或使用PURGE手动删除
# PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);
# ===== 缓存配置 =====
binlog_cache_size=32KB # 事务缓存
binlog_stmt_cache_size=32KB # 非事务语句缓存
max_binlog_cache_size=536870912 # 最大缓存(512MB)
# ===== 日志文件大小 =====
max_binlog_size=1073741824 # 单个日志文件大小(1GB)
# ===== 同步模式 =====
sync_binlog=1 # 0=依赖OS刷新,1=每次提交刷新(安全但慢)
# 生产建议:1 或 N(每N次提交刷新)
5.2 Slave性能优化
INI
# my.cnf - Slave配置
[mysqld]
# ===== 中继日志配置 =====
relay_log=mysql-relay-bin
relay_log_index=mysql-relay-bin.index
relay_log_purge=ON # 自动清理过期中继日志
relay_log_recovery=ON # Slave异常停止时自动恢复
# ===== 复制信息存储 =====
# MySQL 5.7+推荐使用表而非文件
master_info_repository=TABLE # 代替 master.info 文件
relay_log_info_repository=TABLE # 代替 relay-log.info 文件
# ===== 并行复制(MySQL 5.7+) =====
slave_parallel_workers=4 # 并行工作线程数(推荐CPU核数-1)
slave_parallel_type=LOGICAL_CLOCK # 逻辑时钟模式(MySQL 8.0推荐)
# 可选值:DATABASE(基于库)
slave_preserve_commit_order=ON # 保证事务提交顺序一致
# MySQL 5.7:
# slave_parallel_type=DATABASE # 基于库并行(简单但效果一般)
# ===== 网络和连接 =====
slave_net_timeout=60 # 网络超时(秒)
master_connect_retry=60 # 重连间隔
master_retry_count=86400 # 最大重试次数
# ===== Slave性能选项 =====
skip_slave_start=OFF # 启动时自动启动复制
slave_read_only=ON # Slave只读(防止误写)
super_read_only=ON # 即使有SUPER权限也只读
# ===== 半同步复制(可选,提高数据安全性) =====
rpl_semi_sync_slave_enabled=ON
rpl_semi_sync_slave_trace_all_slaves=ON
rpl_semi_sync_slave_timeout=1000
5.3 半同步复制配置
砰
# Master端
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SET GLOBAL rpl_semi_sync_master_enabled = ON;
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 1000; # 1秒超时
# 或在my.cnf中配置
# [mysqld]
# plugin_dir=/usr/lib64/mysql/plugin
# plugin-load=rpl_semi_sync_master=semisync_master.so
# rpl_semi_sync_master_enabled=1
# rpl_semi_sync_master_timeout=1000
# Slave端
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = ON;
# 或在my.cnf中配置
# [mysqld]
# plugin_load=rpl_semi_sync_slave=semisync_slave.so
# rpl_semi_sync_slave_enabled=1
# 验证
mysql> SHOW PLUGINS;
# 查看semisync_master和semisync_slave是否已加载
6. 监控和诊断
6.1 复制状态监控SQL
-- 定期检查Slave状态的完整查询
SHOW SLAVE STATUS\G;
-- 关键指标说明:
-- Slave_IO_State : Slave IO线程的当前状态
-- Slave_IO_Running : IO线程是否运行(应为Yes)
-- Slave_SQL_Running : SQL线程是否运行(应为Yes)
-- Seconds_Behind_Master : 复制延迟秒数(应为0或接近0)
-- Last_IO_Error : IO线程最后错误
-- Last_SQL_Error : SQL线程最后错误
-- Master_Log_File : Master当前日志文件
-- Read_Master_Log_Pos : 读取到的位置
-- Relay_Log_File : 当前中继日志文件
-- Relay_Log_Pos : 中继日志位置
-- Executed_Gtid_Set : 已执行的GTID集合(GTID模式)
6.2 Master监控命令
-- 查看二进制日志状态
SHOW MASTER STATUS;
-- 查看连接到Master的Slave信息
SHOW SLAVE HOSTS;
-- 查看所有二进制日志文件
SHOW BINARY LOGS;
-- 查看二进制日志中的具体事件(调试用)
SHOW BINLOG EVENTS IN 'mysql-bin.000001';
-- 查看Master线程信息
SHOW PROCESSLIST;
6.3 数据一致性检查
SQL
-- 计算表校验和(Master和Slave比对)
-- Master
mysql> CHECKSUM TABLE timinglee.users;
+------------------+----------+
| Table | Checksum |
+------------------+----------+
| timinglee.users | 1234567 |
+------------------+----------+
-- Slave
mysql> CHECKSUM TABLE timinglee.users;
# 校验和应该相同
-- 或使用更高级的工具
-- pt-table-checksum(来自Percona Toolkit)
pt-table-checksum h=172.25.254.10,u=root,p=root
6.4 监控脚本示例
砰
#!/bin/bash
# 监控Slave复制状态
MYSQL_USER="root"
MYSQL_PASS="password"
MYSQL_HOST="localhost"
SLAVE_LAG_THRESHOLD=10 # 延迟告警阈值(秒)
# 获取复制状态
STATUS=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -h$MYSQL_HOST -e "SHOW SLAVE STATUS\G" | grep -E "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_Error")
echo "Replication Status:"
echo "$STATUS"
# 提取关键值
IO_RUNNING=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -h$MYSQL_HOST -e "SHOW SLAVE STATUS\G" | grep "Slave_IO_Running" | awk '{print $2}')
SQL_RUNNING=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -h$MYSQL_HOST -e "SHOW SLAVE STATUS\G" | grep "Slave_SQL_Running" | awk '{print $2}')
LAG=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -h$MYSQL_HOST -e "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master" | awk '{print $2}')
# 告警判断
if [ "$IO_RUNNING" != "Yes" ] || [ "$SQL_RUNNING" != "Yes" ]; then
echo "ALERT: Replication is not running!"
# 发送告警(邮件、钉钉等)
fi
if [ $LAG -gt $SLAVE_LAG_THRESHOLD ]; then
echo "ALERT: Replication lag is $LAG seconds!"
fi
7. 性能优化建议
7.1 并行复制配置方案
INI
# MySQL 5.7 - 基于库的并行复制
[mysqld]
slave_parallel_workers=4
slave_parallel_type=DATABASE
# MySQL 8.0+ - 基于逻辑时钟的并行复制(推荐)
[mysqld]
slave_parallel_workers=8 # 根据CPU核数调整
slave_parallel_type=LOGICAL_CLOCK
slave_preserve_commit_order=ON # 重要:保证提交顺序
slave_parallel_max_queued_events=10000 # 队列大小
slave_parallel_workers_transaction_priority_input=TRANSACTION_WRITE_SET_EXTRACTION
7.2 缓存大小优化
SQL
-- 查看当前配置
SHOW VARIABLES LIKE 'binlog%cache%';
SHOW VARIABLES LIKE 'tmp%';
-- 根据业务特点调整
-- 1. 如果有大事务,增加缓存大小
-- 2. 如果频繁切换日志,减小max_binlog_size
-- 3. 监控缓存溢出情况
7.3 网络优化
INI
[mysqld]
# 减少网络开销
net_read_timeout=30 # 读超时
net_write_timeout=60 # 写超时
max_connections=1000 # 最大连接数
# TCP优化
net_buffer_length=16384 # 网络缓冲
# Slave特定优化
master_heartbeat_period=5000 # Master心跳间隔(毫秒)
7.4 磁盘I/O优化
INI
[mysqld]
# InnoDB日志
innodb_log_file_size=512M # 日志文件大小
innodb_flush_log_at_trx_commit=2 # 0=不刷盘,1=每次刷,2=每秒刷
innodb_flush_method=O_DIRECT # 直接I/O
# 双写缓冲(可选关闭以提升性能,但降低安全性)
innodb_doublewrite=ON # 生产保持ON
# 缓冲池大小(最重要的参数)
innodb_buffer_pool_size=8G # 推荐物理内存的70-80%
# 预加载
innodb_buffer_pool_load_at_startup=ON
innodb_buffer_pool_dump_at_shutdown=ON
8. 常见问题解决
8.1 复制延迟问题
代码
Seconds_Behind_Master > 0 并持续增长
原因分析
- Master写入过快 - Slave无法跟上
- Slave硬件配置不足 - CPU、内存、磁盘慢
- Slave上有大查询 - 锁表,影响复制
- 网络延迟 - Master和Slave之间网络问题
- 单线程复制 - 并发低
解决方案
砰
# 1. 启用并行复制
mysql> SET GLOBAL slave_parallel_workers=4;
mysql> SET GLOBAL slave_parallel_type='LOGICAL_CLOCK';
mysql> STOP SLAVE;
mysql> START SLAVE;
# 2. 检查Slave上的查询
mysql> SHOW PROCESSLIST;
# 杀死长查询:KILL QUERY process_id;
# 3. 检查磁盘I/O
iostat -x 1 5
# 查看await(等待时间)是否过长
# 4. 增加Slave硬件资源
# - 增加CPU核数
# - 增加内存
# - 使用SSD替换HDD
# 5. 启用binlog压缩(MySQL 8.0.20+)
mysql> SET GLOBAL binlog_compression=ON;
# 在my.cnf中:binlog_compression=ON
8.2 复制错误处理
Slave_SQL_Running:
-- 查看具体错误
SHOW SLAVE STATUS\G;
# Last_SQL_Error会显示错误内容
-- 常见错误:
-- 1. Duplicate key error - 主键冲突
-- 2. Table doesn't exist - 表不存在
-- 3. Out of range value - 值超出范围
-- 解决方案1:跳过错误(仅用于测试)
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;
-- 解决方案2:手动修复(推荐)
-- 在Master上导出数据:
mysqldump -u root -p db.table > table.sql
-- 在Slave上导入:
mysql -u root -p db < table.sql
-- 重新启动复制:
STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO ...;
START SLAVE;
-- 解决方案3:使用Percona XtraDB Cluster
# 更安全的高可用方案
8.3 主从数据不一致
症状
代码
Master和Slave上同一张表的数据不同
校验和不匹配
预防措施
-- 使用GTID + ROW日志格式(最安全的组合)
-- my.cnf配置:
-- [mysqld]
-- gtid_mode=ON
-- enforce_gtid_consistency=ON
-- binlog_format=ROW
-- 启用从库只读
SET GLOBAL read_only = ON;
SET GLOBAL super_read_only = ON; # 即使SUPER用户也只读
-- 启用半同步复制
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = ON;
SET GLOBAL rpl_semi_sync_master_timeout = 1000;
修复方案
# 方案1:使用pt-table-sync(Percona)
pt-table-sync --execute h=master_ip,u=root,p=password \
h=slave_ip,u=root,p=password
# 方案2:全量重新同步
# Master端
mysqldump --single-transaction --master-data=2 -A > backup.sql
# Slave端
STOP SLAVE;
mysql < backup.sql
CHANGE MASTER TO MASTER_LOG_FILE='...', MASTER_LOG_POS=...;
START SLAVE;
# 方案3:使用Percona XtraDB Cluster(自动保证一致性)
8.4 网络连接问题
代码
Slave_IO_State: Connecting to master
Slave_IO_Running: Connecting
Lost connection to MySQL server
检查清单
# 1. 网络连接测试
ping 172.25.254.10
telnet 172.25.254.10 3306
# 2. 防火墙检查
iptables -L -n | grep 3306
# 或
firewall-cmd --list-all
# 3. MySQL权限验证
mysql -u swp -p'swp@123456' -h 172.25.254.10
# 4. 查看错误日志
tail -f /var/log/mysql/error.log
# 5. 检查Master是否接受Slave连接
mysql> SHOW SLAVE HOSTS; # 查看连接状态
# 6. 增加超时时间
mysql> SET GLOBAL master_connect_retry = 120;
mysql> SET GLOBAL slave_net_timeout = 120;
8.5 如何重置复制
# 完全重置复制
STOP SLAVE;
RESET SLAVE; # 删除复制信息
# 重新配置
CHANGE MASTER TO
MASTER_HOST='172.25.254.10',
MASTER_USER='swp',
MASTER_PASSWORD='swp@123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=659;
# 重新启动
START SLAVE;
# 验证
SHOW SLAVE STATUS\G;
9. 高级架构
9.1 一主多从架构
Code
Master (Node1)
/ | \
Slave Slave Slave
(Node2) (Node3) (Node4)
优点:
- 读请求分散到多个Slave
- 容错能力强
- 备份可以从任何Slave进行
配置:
bash
# 在Master上为每个Slave创建不同的复制用户(可选)
GRANT REPLICATION SLAVE ON *.* TO 'repl2'@'172.25.254.11';
GRANT REPLICATION SLAVE ON *.* TO 'repl3'@'172.25.254.12';
# 每个Slave独立配置
# Node2、Node3、Node4都连接到Master
9.2 链式复制(主-继电-从)
代码
Master (Node1)
|
↓
Relay Master (Node2) ← 既是Node1的Slave,又是Node3的Master
|
↓
Slave (Node3)
优点:
- 减少Master的复制连接数
- 适合跨地域部署
配置:
# Node2配置(既是Slave又是Master)
# my.cnf配置
[mysqld]
server-id=20
log-bin=mysql-bin
relay-log=mysql-relay-bin
# Node2作为Slave连接Node1
CHANGE MASTER TO
MASTER_HOST='172.25.254.10',
MASTER_USER='swp',
MASTER_PASSWORD='swp@123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=659;
START SLAVE;
# Node3作为Slave连接Node2
CHANGE MASTER TO
MASTER_HOST='172.25.254.11',
MASTER_USER='swp',
MASTER_PASSWORD='swp@123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=659;
START SLAVE;
9.3 环形复制(MultiMaster)
代码
Node1 ↔ Node2
↓ ↑
← ← ←
警告:
- 容易产生复制循环
- 需要严格控制server-id
- 不推荐用于一般生产环境
安全配置:
# Node1 - my.cnf
[mysqld]
server-id=10
log-bin=mysql-bin
log_slave_updates=ON # 重要:Relay日志也要记录
binlog-ignore-db=mysql,sys
# Node2 - my.cnf
[mysqld]
server-id=20
log-bin=mysql-bin
log_slave_updates=ON
binlog-ignore-db=mysql,sys
# Node1连接Node2
mysql> CHANGE MASTER TO
MASTER_HOST='172.25.254.11',
MASTER_USER='swp',
MASTER_PASSWORD='swp@123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=659;
START SLAVE;
# Node2连接Node1
mysql> CHANGE MASTER TO
MASTER_HOST='172.25.254.10',
MASTER_USER='swp',
MASTER_PASSWORD='swp@123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=659;
START SLAVE;
10. 安全最佳实践
10.1 网络安全
[mysqld]
# 绑定到特定IP(不要使用0.0.0.0)
bind-address=172.25.254.10
# 禁用不安全选项
skip_external_locking
skip_name_resolve # 加快连接,避免DNS问题
# SSL/TLS支持
ssl=ON
ssl_ca=/path/to/ca.pem
ssl_cert=/path/to/server-cert.pem
ssl_key=/path/to/server-key.pem
10.2 用户权限管理
-- 创建只读用户
CREATE USER 'readonly'@'172.25.254.%' IDENTIFIED BY 'password';
GRANT SELECT ON *.* TO 'readonly'@'172.25.254.%';
-- 创建复制用户(最小权限)
CREATE USER 'repl'@'172.25.254.11' IDENTIFIED WITH mysql_native_password BY 'password';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'172.25.254.11';
-- 定期审计权限
SELECT user, host, Select_priv, Insert_priv, Update_priv, Delete_priv FROM mysql.user;
-- 定期更新密码
ALTER USER 'repl'@'172.25.254.11' IDENTIFIED BY 'newpassword';
10.3 备份策略
# 物理备份(热备,推荐)
xtrabackup --backup --target-dir=/backup/$(date +%Y%m%d)
# 恢复
xtrabackup --prepare --target-dir=/backup/20260410
xtrabackup --copy-back --target-dir=/backup/20260410
# 逻辑备份(冷备)
mysqldump --single-transaction --master-data=2 -A > backup_$(date +%Y%m%d).sql
# 增量备份(基于二进制日志)
# 保存Master的二进制日志
# 定期上传到备份服务器
10.4 密码管理
# 生成强密码(至少12位,包含大小写、数字、特殊符号)
echo "swp@Mysql_2024_$(date +%s)" | base64
# 使用密码管理工具
# 或存储在安全的配置文件中,并限制权限
chmod 600 /etc/my.cnf
11. 监控和告警
11.1 Prometheus监控指标
# prometheus.yml
scrape_configs:
- job_name: 'mysql'
static_configs:
- targets: ['127.0.0.1:9104'] # MySQL Exporter
# 关键指标:
# mysql_global_status_seconds_behind_master # 复制延迟
# mysql_slave_status_io_running # IO线程状态
# mysql_slave_status_sql_running # SQL线程状态
# mysql_global_status_binlog_cache_use # 缓存使用
# mysql_global_status_bytes_sent # 发送字节
11.2 告警规则示例
YAML
# prometheus告警规则
groups:
- name: mysql_alerts
rules:
- alert: MySQLReplicationDown
expr: mysql_slave_status_io_running == 0 or mysql_slave_status_sql_running == 0
for: 1m
annotations:
summary: "MySQL Slave Replication is down"
- alert: MySQLReplicationLag
expr: mysql_global_status_seconds_behind_master > 30
for: 5m
annotations:
summary: "MySQL Replication lag is {{ $value }} seconds"
- alert: MySQLBinlogUsage
expr: node_filesystem_avail_bytes{mountpoint="/data"} / node_filesystem_size_bytes{mountpoint="/data"} < 0.2
for: 10m
annotations:
summary: "MySQL binlog disk usage is above 80%"
11.3 监控仪表盘配置(Grafana)
代码
关键仪表盘:
1. Replication Status Dashboard
- Slave IO Running
- Slave SQL Running
- Seconds Behind Master
2. Performance Dashboard
- QPS (Queries Per Second)
- TPS (Transactions Per Second)
- Slow Queries
3. Resource Dashboard
- CPU Usage
- Memory Usage
- Disk I/O
- Network I/O
4. Binlog Dashboard
- Binlog File Size
- Binlog Rotation Rate
- Binlog Space Usage
12. 维护和升级
12.1 日常维护清单
代码
每日检查:
☑ Slave复制状态 (SHOW SLAVE STATUS)
☑ 复制延迟是否正常
☑ 错误日志中是否有异常
每周检查:
☑ 二进制日志大小和数量
☑ 中继日志大小
☑ 磁盘空间使用情况
☑ 备份是否成功
每月检查:
☑ Master性能和连接数
☑ 慢查询日志分析
☑ 权限审计
☑ 测试故障转移流程
12.2 MySQL版本升级
# 升级前准备
1. 备份所有数据库
mysqldump -A --single-transaction > backup.sql
2. 记录当前配置
SHOW MASTER STATUS;
SHOW SLAVE STATUS;
3. 停止应用写入
# 升级Slave(先升级从库)
1. 停止Slave
STOP SLAVE;
2. 升级MySQL版本
/etc/init.d/mysqld stop
apt-get upgrade mysql-server # 或 yum upgrade mysql-server
/etc/init.d/mysqld start
mysql_upgrade
3. 验证
SHOW SLAVE STATUS\G;
START SLAVE;
# 升级Master(等所有Slave升级后)
# 步骤同上,但注意选择合适的时间窗口
12.3 参数调整(不需要重启)
SQL
-- 动态修改参数(仅当前session有效)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2;
-- 永久修改(需要重启生效)
-- 修改/etc/my.cnf后重启MySQL
-- 查看可修改的变量
SHOW VARIABLES LIKE 'can_use_dynamic_%';
13. 故障恢复流程
13.1 Master宕机恢复
# 1. 确认Master无法恢复
ping master_ip # 无响应
mysql -h master_ip -u root # 无法连接
# 2. 选择最新的Slave作为新Master
SHOW SLAVE STATUS\G; # 比较Read_Master_Log_Pos
# 选择日志位置最靠后的Slave
# 3. 在新Master上
STOP SLAVE;
RESET SLAVE;
# 现在这个Slave变成了Master
# 4. 其他Slave连接到新Master
CHANGE MASTER TO
MASTER_HOST='new_master_ip',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=xxx;
START SLAVE;
# 5. 验证新集群
SHOW MASTER STATUS; # 在新Master上
SHOW SLAVE STATUS\G; # 在其他Slave上
13.2 Slave宕机恢复
# 简单恢复(如果中继日志完好)
STOP SLAVE;
START SLAVE;
# 自动恢复
# 彻底恢复(如果中继日志损坏)
STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO ...; # 重新配置
START SLAVE;
# 快速追上Master(使用并行复制)
SET GLOBAL slave_parallel_workers=8;
START SLAVE;
13.3 数据恢复流程
# 场景1:误操作删除了重要数据
# Step1:停止Slave复制(防止继续损坏)
STOP SLAVE;
# Step2:从备份恢复数据
# 找到备份点的二进制日志位置
mysql < /backup/backup_20260410.sql
# Step3:重新同步
RESET SLAVE;
CHANGE MASTER TO ...;
START SLAVE;
# 场景2:用户误操作(有Binlog)
# 利用Binlog时间点恢复
mysqlbinlog --start-datetime='2026-04-10 10:00:00' \
--stop-datetime='2026-04-10 11:00:00' \
/data/mysql/mysql-bin.000001 | mysql
# 场景3:完整的数据库恢复
# 结合物理备份和增量备份恢复到任意时间点
14. 完整配置示例
14.1 生产级Master配置
# /etc/my.cnf - MySQL 8.0 Master完整配置
[mysqld]
# ========== 基础配置 ==========
server-id=10
port=3306
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
bind-address=172.25.254.10
skip_external_locking
skip_name_resolve
# ========== InnoDB引擎 ==========
default-storage-engine=InnoDB
innodb_buffer_pool_size=8G # 物理内存的70-80%
innodb_file_per_table=ON # 独立表空间
innodb_log_file_size=512M
innodb_flush_log_at_trx_commit=1 # 生产环保持1
innodb_flush_method=O_DIRECT
innodb_doublewrite=ON
innodb_buffer_pool_load_at_startup=ON
innodb_buffer_pool_dump_at_shutdown=ON
# ========== 二进制日志(复制配置) ==========
log-bin=mysql-bin
binlog_format=ROW
binlog_row_image=MINIMAL
expire_logs_days=7
max_binlog_size=1G
binlog_cache_size=32KB
binlog_stmt_cache_size=32KB
sync_binlog=1 # 每次提交同步日志
# ========== 半同步复制 ==========
plugin-load=rpl_semi_sync_master=semisync_master.so
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
# ========== GTID(可选) ==========
# gtid_mode=ON
# enforce_gtid_consistency=ON
# master_info_repository=TABLE
# relay_log_info_repository=TABLE
# ========== 日志过滤(可选) ==========
# binlog-do-db=business_db
# binlog-ignore-db=mysql,sys,performance_schema,information_schema
# ========== 慢查询日志 ==========
slow_query_log=1
slow_query_log_file=/data/mysql/slow.log
long_query_time=2
log-queries-not-using-indexes
# ========== 错误日志 ==========
log-error=/data/mysql/error.log
log_error_verbosity=2
# ========== 查询缓存(MySQL 5.7+不推荐) ==========
# query_cache_type=0
# query_cache_size=0
# ========== 最大连接数 ==========
max_connections=1000
max_connect_errors=100
# ========== 其他优化 ==========
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
default_time_zone='+8:00'
[mysqldump]
quick
quote-names
max_allowed_packet=16M
[mysql]
# no-auto-rehash
[mysqld_safe]
log-error=/data/mysql/error.log
pid-file=/data/mysql/mysqld.pid
14.2 生产级Slave配置
# /etc/my.cnf - MySQL 8.0 Slave完整配置
[mysqld]
# ========== 基础配置 ==========
server-id=20
port=3306
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
bind-address=172.25.254.11
skip_external_locking
skip_name_resolve
# ========== InnoDB引擎 ==========
default-storage-engine=InnoDB
innodb_buffer_pool_size=8G
innodb_file_per_table=ON
innodb_log_file_size=512M
innodb_flush_log_at_trx_commit=2 # Slave可以设为2(性能更好)
innodb_flush_method=O_DIRECT
innodb_doublewrite=ON
innodb_buffer_pool_load_at_startup=ON
innodb_buffer_pool_dump_at_shutdown=ON
# ========== 复制配置 ==========
log-bin=mysql-bin
relay-log=mysql-relay-bin
relay-log-index=mysql-relay-bin.index
relay_log_purge=ON
relay_log_recovery=ON
# ========== Slave专用优化 ==========
master_info_repository=TABLE
relay_log_info_repository=TABLE
skip_slave_start=OFF
read_only=ON # Slave只读
super_read_only=ON # SUPER用户也只读
slave_net_timeout=60
master_connect_retry=60
master_retry_count=86400
# ========== 并行复制(MySQL 8.0+) ==========
slave_parallel_workers=8 # CPU核数-1
slave_parallel_type=LOGICAL_CLOCK
slave_preserve_commit_order=ON
slave_parallel_max_queued_events=10000
# ========== 半同步复制 ==========
plugin-load=rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled=1
# ========== GTID(可选) ==========
# gtid_mode=ON
# enforce_gtid_consistency=ON
# master_info_repository=TABLE
# relay_log_info_repository=TABLE
# ========== 日志过滤(可选) ==========
# replicate-do-db=business_db
# replicate-ignore-db=mysql,sys,performance_schema,information_schema
# ========== 慢查询日志 ==========
slow_query_log=1
slow_query_log_file=/data/mysql/slow.log
long_query_time=2
# ========== 错误日志 ==========
log-error=/data/mysql/error.log
log_error_verbosity=2
# ========== 最大连接数 ==========
max_connections=1000
max_connect_errors=100
# ========== 其他优化 ==========
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
default_time_zone='+8:00'
[mysqldump]
quick
quote-names
max_allowed_packet=16M
[mysql]
# no-auto-rehash
[mysqld_safe]
log-error=/data/mysql/error.log
pid-file=/data/mysql/mysqld.pid
15. 快速参考
15.1 常用命令速查表
| 命令 | 说明 |
|---|---|
SHOW MASTER STATUS; |
查看Master状态 |
SHOW SLAVE STATUS\G; |
查看Slave状态 |
SHOW SLAVE HOSTS; |
查看Master上连接的Slave |
SHOW BINARY LOGS; |
查看所有日志文件 |
SHOW BINLOG EVENTS; |
查看日志中的事件 |
START SLAVE; |
启动Slave |
STOP SLAVE; |
停止奴隶 |
RESET SLAVE; |
重置Slave |
FLUSH BINARY LOGS; |
轮转日志文件 |
PURGE BINARY LOGS BEFORE '2026-04-10 00:00:00'; |
删除旧日志 |
15.2 常见参数调整
SQL
-- 并行复制
SET GLOBAL slave_parallel_workers=4;
SET GLOBAL slave_parallel_type='LOGICAL_CLOCK';
-- 只读
SET GLOBAL read_only=ON;
-- 日志
SET GLOBAL binlog_format='ROW';
SET GLOBAL binlog_row_image='MINIMAL';
-- 网络超时
SET GLOBAL slave_net_timeout=60;
SET GLOBAL master_connect_retry=60;
-- 检查设置是否生效
SHOW VARIABLES LIKE 'slave_parallel%';
总结
MySQL主从复制的关键要点:
- 正确的配置 ✓
- 设置唯一的server-id
- 启用二进制日志
- 为Slave创建专用复制用户
- 选择合适的日志格式 ✓
- ROW格式:安全但日志大,推荐
- STATEMENT格式:日志小但可能不一致
- MIXED格式:折中方案
- 监控和告警 ✓
- 定期检查显示从属状态
- 监控复制延迟
- 及时处理复制错误
- 性能优化 ✓
- 启用并行复制
- 优化缓存大小
- 使用半同步复制
- 高可用架构 ✓
- 一主多从
- 定期备份
- 故障自动转移
- 安全防护 ✓
- 强密码
- 限制用户权限
- 网络隔离
参考资源
最后更新 : 2026-04-10
版本 : 1.0
适用范围: MySQL 5.7+, 特别是MySQL 8.0
📋 **完整目录结构**:
- 第一部分:基础配置(my.cnf、用户权限、复制初始化)
- 第二部分:主从复制配置(详细的配置步骤和验证)
- 第三部分:功能验证(测试和数据同步验证)
- 第四部分:优化配置(性能优化、监控、故障排查)
- 高级内容(架构设计、安全管理、维护升级)
🎯 **主要特点**:
- ✅ 详细的配置示例(包含MySQL 8.0特定配置)
- ✅ 完整的SQL命令示例
- ✅ 性能优化建议
- ✅ 常见问题解决方案
- ✅ 生产级完整配置模板
- ✅ 故障恢复流程
- ✅ 监控和告警方案
| 重置Slave |
| `FLUSH BINARY LOGS;` | 轮转日志文件 |
| `PURGE BINARY LOGS BEFORE '2026-04-10 00:00:00';` | 删除旧日志 |
### 15.2 常见参数调整
SQL
-- 并行复制
SET GLOBAL slave_parallel_workers=4;
SET GLOBAL slave_parallel_type='LOGICAL_CLOCK';
-- 只读
SET GLOBAL read_only=ON;
-- 日志
SET GLOBAL binlog_format='ROW';
SET GLOBAL binlog_row_image='MINIMAL';
-- 网络超时
SET GLOBAL slave_net_timeout=60;
SET GLOBAL master_connect_retry=60;
-- 检查设置是否生效
SHOW VARIABLES LIKE 'slave_parallel%';
------
## 总结
MySQL主从复制的关键要点:
1. **正确的配置** ✓
- 设置唯一的server-id
- 启用二进制日志
- 为Slave创建专用复制用户
2. **选择合适的日志格式** ✓
- ROW格式:安全但日志大,推荐
- STATEMENT格式:日志小但可能不一致
- MIXED格式:折中方案
3. **监控和告警** ✓
- 定期检查显示从属状态
- 监控复制延迟
- 及时处理复制错误
4. **性能优化** ✓
- 启用并行复制
- 优化缓存大小
- 使用半同步复制
5. **高可用架构** ✓
- 一主多从
- 定期备份
- 故障自动转移
6. **安全防护** ✓
- 强密码
- 限制用户权限
- 网络隔离
------
## 参考资源
- [MySQL官方文档 - 复制](https://dev.mysql.com/doc/refman/8.0/en/replication.html)
- [Percona 工具 - pt-table-checksum](https://www.percona.com/doc/percona-toolkit/LATEST/pt-table-checksum.html)
- [MySQL官方文档 - GTID](https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html)
- [Percona XtraBackup文档](https://docs.percona.com/percona-xtrabackup/)
------
**最后更新**: 2026-04-10
**版本**: 1.0
**适用范围**: MySQL 5.7+, 特别是MySQL 8.0
📋 完整目录结构:
- 第一部分:基础配置(my.cnf、用户权限、复制初始化)
- 第二部分:主从复制配置(详细的配置步骤和验证)
- 第三部分:功能验证(测试和数据同步验证)
- 第四部分:优化配置(性能优化、监控、故障排查)
- 高级内容(架构设计、安全管理、维护升级)
🎯 主要特点:
- ✅ 详细的配置示例(包含MySQL 8.0特定配置)
- ✅ 完整的SQL命令示例
- ✅ 性能优化建议
- ✅ 常见问题解决方案
- ✅ 生产级完整配置模板
- ✅ 故障恢复流程
- ✅ 监控和告警方案