1. 为什么需要MySQL主从架构?
在互联网应用快速发展的今天,数据库作为核心数据存储组件,其可用性和性能直接影响业务连续性。我曾参与过一个电商项目,在促销活动期间,单台MySQL服务器突然宕机,导致整个网站瘫痪近2小时,损失惨重。这次事故后,我们决定引入主从复制架构。
MySQL主从复制(Replication)是指将主库(Master)的数据变更同步到一个或多个从库(Slave)的过程。这种架构带来的核心价值包括:
- 高可用性:当主库出现故障时,可以快速切换到从库继续提供服务
- 读写分离:主库处理写操作,从库处理读操作,有效分担负载
- 数据备份:从库可以作为实时备份,避免数据丢失
- 数据分析:可以在从库上执行耗时的报表查询,不影响主库性能
MySQL 8.0在复制机制上做了多项改进,包括:
- 基于WriteSet的并行复制,大幅提升同步效率
- 事务性数据字典,使DDL操作也能安全复制
- 组复制(Group Replication)增强,提供更高可用性
注意:虽然主从架构能提高可用性,但它不是完全的故障转移方案。要实现自动故障转移,还需要配合其他工具如MHA或Orchestrator。
2. 环境准备与安装MySQL 8.0
2.1 服务器规划建议
在生产环境中,我建议至少使用两台独立服务器:
- 主库服务器:建议配置较高的CPU和内存,特别是写入密集型应用
- 从库服务器:根据读负载需求配置,磁盘I/O性能很重要
以下是我们在实际项目中的典型配置:
| 组件 | CPU | 内存 | 磁盘 | 网络 |
|---|---|---|---|---|
| 主库(Master) | 8核 | 32G | SSD RAID | 千兆网卡 |
| 从库(Slave) | 4核 | 16G | SSD | 千兆网卡 |
2.2 MySQL 8.0安装步骤
以Ubuntu 20.04为例,安装MySQL 8.0:
# 添加MySQL官方APT仓库 wget https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb sudo dpkg -i mysql-apt-config_0.8.22-1_all.deb sudo apt update # 安装MySQL服务器 sudo apt install mysql-server # 安全配置(设置root密码等) sudo mysql_secure_installation对于CentOS/RHEL系统:
# 添加MySQL Yum仓库 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-6.noarch.rpm # 安装MySQL服务器 sudo yum install mysql-community-server # 启动服务 sudo systemctl start mysqld sudo systemctl enable mysqld安装完成后,检查版本:
mysql> SELECT VERSION(); +-----------+ | VERSION() | +-----------+ | 8.0.28 | +-----------+提示:生产环境建议禁用MySQL的匿名账户,并为root设置强密码。我曾经遇到过因弱密码导致的安全事件。
3. 主库配置详解
3.1 修改主库配置文件
编辑/etc/mysql/mysql.conf.d/mysqld.cnf(路径可能因系统而异),在[mysqld]段添加:
[mysqld] server-id = 1 log_bin = mysql-bin binlog_format = ROW binlog_row_image = FULL expire_logs_days = 7 max_binlog_size = 100M sync_binlog = 1 binlog_group_commit_sync_delay = 100 binlog_group_commit_sync_no_delay_count = 10关键参数说明:
server-id:必须唯一,主从不能相同log_bin:启用二进制日志,这是复制的基础binlog_format=ROW:建议使用行格式,更安全可靠sync_binlog=1:每次事务提交都同步binlog到磁盘,确保数据安全
3.2 创建复制专用账户
在主库上执行:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'SecurePass123!'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;注意:MySQL 8.0默认使用caching_sha2_password认证插件,如果从库是旧版本MySQL,需要使用mysql_native_password。
3.3 获取主库初始状态
锁定主库并记录二进制日志位置:
FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS;输出类似:
+------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000003 | 785 | | | | +------------------+----------+--------------+------------------+-------------------+记下File和Position值,配置从库时会用到。完成后解锁:
UNLOCK TABLES;4. 从库配置与同步启动
4.1 从库基础配置
编辑从库的my.cnf文件:
[mysqld] server-id = 2 relay_log = mysql-relay-bin read_only = 1 super_read_only = 1 log_slave_updates = 1重要参数:
server-id必须与主库不同read_only和super_read_only确保从库不会被意外写入log_slave_updates允许从库作为其他从库的主库(级联复制)
4.2 初始化从库数据
有多种方式初始化从库数据:
方法1:使用mysqldump(适合小型数据库)
# 在主库执行 mysqldump -u root -p --all-databases --master-data=2 > dbdump.sql # 在从库导入 mysql -u root -p < dbdump.sql方法2:使用克隆插件(MySQL 8.0+推荐)
-- 在从库执行 INSTALL PLUGIN clone SONAME 'mysql_clone.so'; SET GLOBAL clone_valid_donor_list = 'master_ip:3306'; -- 开始克隆 CLONE INSTANCE FROM 'repl'@'master_ip':3306 IDENTIFIED BY 'SecurePass123!';方法3:使用Percona XtraBackup(适合大型数据库)
# 在主库执行 xtrabackup --backup --user=root --password=yourpassword --target-dir=/path/to/backup xtrabackup --prepare --target-dir=/path/to/backup # 将备份复制到从库后恢复 xtrabackup --copy-back --target-dir=/path/to/backup chown -R mysql:mysql /var/lib/mysql4.3 启动复制进程
在从库上执行:
CHANGE MASTER TO MASTER_HOST='master_ip', MASTER_USER='repl', MASTER_PASSWORD='SecurePass123!', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=785; START SLAVE;检查复制状态:
SHOW SLAVE STATUS\G关键指标检查:
Slave_IO_Running和Slave_SQL_Running都应为YesSeconds_Behind_Master显示复制延迟秒数Last_IO_Error和Last_SQL_Error应为空
5. 高级配置与性能优化
5.1 半同步复制配置
MySQL默认采用异步复制,可能丢失少量数据。半同步复制确保至少一个从库收到数据后才返回给客户端:
在主库和从库安装插件:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';主库配置:
SET GLOBAL rpl_semi_sync_master_enabled = 1; SET GLOBAL rpl_semi_sync_master_timeout = 10000; # 10秒超时从库配置:
SET GLOBAL rpl_semi_sync_slave_enabled = 1;5.2 多线程复制优化
MySQL 8.0默认启用基于WriteSet的并行复制:
SHOW VARIABLES LIKE 'slave_parallel%';建议配置:
slave_parallel_workers = 8 slave_parallel_type = LOGICAL_CLOCK5.3 复制过滤配置
有时不需要复制所有数据库:
# 只复制特定数据库 CHANGE REPLICATION FILTER REPLICATE_DO_DB = (db1, db2); # 忽略特定表 CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('db1.log_%', 'db2.temp_%');6. 日常监控与故障处理
6.1 关键监控指标
建议监控以下指标:
| 指标名称 | 正常值 | 检查命令 |
|---|---|---|
| 复制状态 | Slave_IO/SQL_Running=Yes | SHOW SLAVE STATUS\G |
| 复制延迟(秒) | <30 | SHOW SLAVE STATUS\G |
| 主库二进制日志位置 | 持续增长 | SHOW MASTER STATUS |
| 从库中继日志应用位置 | 与主库位置接近 | SHOW SLAVE STATUS\G |
| 复制错误 | 无 | SHOW SLAVE STATUS\G |
6.2 常见问题处理
问题1:复制中断(Last_SQL_Error显示错误)
解决方法:
STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; # 跳过1个错误事件 START SLAVE;或者(对于主键冲突等):
STOP SLAVE; SET @@GLOBAL.slave_exec_mode='IDEMPOTENT'; # 启用幂等模式 START SLAVE;问题2:主从数据不一致
使用pt-table-checksum检查:
pt-table-checksum --replicate=test.checksums h=master_ip,u=root,p=yourpassword pt-table-sync --replicate=test.checksums h=master_ip,u=root,p=yourpassword --print问题3:网络中断导致复制延迟
可以临时调整:
STOP SLAVE; CHANGE MASTER TO MASTER_CONNECT_RETRY=10, MASTER_RETRY_COUNT=36; START SLAVE;7. 主从切换演练
定期演练主从切换非常重要。以下是手动切换步骤:
步骤1:提升从库为主库
在从库执行:
STOP SLAVE; RESET MASTER; SET GLOBAL read_only=OFF; SET GLOBAL super_read_only=OFF;步骤2:配置原主库为新从库
在原主库执行:
RESET SLAVE ALL; CHANGE MASTER TO MASTER_HOST='new_master_ip', MASTER_USER='repl', MASTER_PASSWORD='SecurePass123!', MASTER_AUTO_POSITION=1; START SLAVE;步骤3:应用连接切换
修改应用配置,将写操作指向新主库。建议使用中间件如ProxySQL或MySQL Router实现透明切换。
我在实际运维中发现,定期演练能显著提高故障时的恢复速度。曾经有一次生产故障,因为平时演练充分,我们仅用3分钟就完成了主从切换,业务几乎无感知。