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 并持续增长 ##### 原因分析 1. **Master写入过快** - Slave无法跟上 2. **Slave硬件配置不足** - CPU、内存、磁盘慢 3. **Slave上有大查询** - 锁表,影响复制 4. **网络延迟** - Master和Slave之间网络问题 5. **单线程复制** - 并发低 ##### 解决方案 砰 # 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主从复制的关键要点: 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命令示例 - ✅ 性能优化建议 - ✅ 常见问题解决方案 - ✅ 生产级完整配置模板 - ✅ 故障恢复流程 - ✅ 监控和告警方案 | 重置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命令示例 * ✅ 性能优化建议 * ✅ 常见问题解决方案 * ✅ 生产级完整配置模板 * ✅ 故障恢复流程 * ✅ 监控和告警方案 ``` ```