在 Linux 云服务器(CentOS/Ubuntu)上配置 MySQL 主从复制,核心不在于“能不能通”,而在于数据一致性、网络安全性和故障恢复能力。很多教程只讲步骤,不讲坑。作为在云上摸爬滚打多年的运维,我把这套流程拆解为生产环境可用的标准实践。
以下以 MySQL 8.0+ 为例(目前主流版本),涵盖主库(Master)、从库(Slave)配置及关键安全加固。
一、 前置准备:云环境特有的注意事项
- 安全组/防火墙策略
- 不要直接开放
3306端口给0.0.0.0/0。 - 正确做法:在主库的安全组中,仅允许从库的私有 IP 访问
3306端口。如果是跨可用区或跨地域,需通过专线或 XX 打通内网。
- 不要直接开放
- 时钟同步
- 主从延迟的一个常见原因是服务器时间不同步。确保两台机器都配置了 NTP 服务,误差控制在毫秒级。
- 二进制日志格式
- 强烈建议使用
ROW模式(Row-based replication)。相比STATEMENT和MIXED,ROW能更精确地记录数据变更,减少因函数不确定性导致的主从数据不一致问题。
- 强烈建议使用
二、 主库(Master)配置
假设主库 IP 为 192.168.1.10,从库 IP 为 192.168.1.20。
1. 修改配置文件 (my.cnf)
编辑 /etc/my.cnf (CentOS) 或 /etc/mysql/mysql.conf.d/mysqld.cnf (Ubuntu)。
[mysqld]
# 唯一 Server ID,必须全局唯一,且不能与从库重复
server-id = 1
# 开启二进制日志,这是复制的基础
log-bin = mysql-bin
# 推荐设置:基于行的复制
binlog-format = ROW
# 建议:指定需要复制的数据库,避免全量同步带来的性能损耗
# binlog-do-db = my_database_name
# 建议:忽略不需要复制的系统库
# replicate-ignore-db = mysql,performance_schema,sys
# 可选:如果主库压力极大,可考虑半同步复制插件以提升数据安全性(下文详述)
注意:修改后重启 MySQL 服务。
2. 创建复制专用账号
出于安全原则,严禁使用 root 用户进行复制。创建一个权限最小化的专用账号。
-- 登录主库执行
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'StrongPassword123!';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
%表示允许从任意 IP 连接,但结合第一步的安全组限制,实际只有从库能连。- 密码务必符合复杂度要求。
3. 获取当前 Binlog 位置
在执行数据备份前,先锁定表并查看状态:
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;
记下输出中的 File 名称(如 mysql-bin.000003)和 Position 值(如 154)。这一步至关重要,后续从库将从这个位置开始同步。
三、 从库(Slave)配置
假设从库 IP 为 192.168.1.20。
1. 修改配置文件 (my.cnf)
[mysqld]
# 唯一的 Server ID,必须不同于主库
server-id = 2
# 开启中继日志
relay-log = relay-bin
# 可选:如果从库也用于读负载,可以开启只读模式防止误写
read-only = 1
# 可选:跳过某些错误继续同步(谨慎使用,通常用于临时应急)
# slave-skip-errors = 1062,1032
重启 MySQL 服务。
2. 导入初始数据
将主库锁表期间导出的数据(使用 mysqldump 或物理备份工具如 XtraBackup)恢复到从库。
- 关键点:确保从库的数据状态与主库在
FLUSH TABLES WITH READ LOCK那一刻完全一致。
3. 配置复制关系
解锁主库后(在主库执行 UNLOCK TABLES;),在从库执行以下命令建立连接:
CHANGE MASTER TO
MASTER_HOST='192.168.1.10',
MASTER_USER='repl_user',
MASTER_PASSWORD='StrongPassword123!',
MASTER_LOG_FILE='mysql-bin.000003', -- 替换为主库 SHOW MASTER STATUS 的结果
MASTER_LOG_POS=154; -- 替换为主库 SHOW MASTER STATUS 的结果
START SLAVE;
MySQL 8.0+ 新语法提示:
在新版本中,推荐使用CHANGE REPLICATION SOURCE TO替代CHANGE MASTER TO,语义更清晰。CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.1.10', SOURCE_USER='repl_user', SOURCE_PASSWORD='StrongPassword123!', SOURCE_LOG_FILE='mysql-bin.000003', SOURCE_LOG_POS=154; START REPLICA;
4. 验证状态
SHOW SLAVE STATUSG
重点关注以下字段:
Slave_IO_Running: YesSlave_SQL_Running: YesSeconds_Behind_Master: 0(或较小数值)Last_Error: 无报错信息
如果 Seconds_Behind_Master 不为 0,说明存在延迟,需检查主库写入压力或网络状况。
四、 进阶:提升高可用与安全性的关键手段
仅仅跑通主从是不够的,生产环境还需要考虑以下两点:
1. 启用半同步复制(Semi-Sync Replication)
默认异步复制下,主库写完 Binlog 就返回成功,若此时主库宕机,从库可能丢失数据。半同步复制要求至少一个从库接收并确认 Binlog 后才返回客户端成功。
安装插件(MySQL 8.0+):
在主库和从库都执行:
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 = 1000; -- 超时1秒后降级为异步,防止阻塞业务
-- 从库设置
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
注意:启用半同步后,重启从库可能需要重新加载插件或调整配置。
2. 监控与告警
不要依赖人工 SHOW SLAVE STATUS。接入 Prometheus + mysqld_exporter,或者使用 Zabbix、阿里云 RDS 监控等工具。
核心监控指标:
- Slave_IO_Running / Slave_SQL_Running 状态
- Seconds_Behind_Master 趋势
- Binlog 大小增长速率
- I/O 线程和 SQL 线程的错误计数
五、 常见坑与排查指南
-
Last_Error: Could not execute Write_rows event- 原因:通常是主从数据结构不一致,或者从库被意外修改了数据。
- 解决:检查
read-only是否生效;检查是否有应用直连从库写入数据。如果是偶发冲突,可暂时跳过错误(不推荐长期方案),根本解决是保证从库只读。
-
Got fatal error 1236 from master when reading data from binary log- 原因:Binlog 文件损坏或位置点错误。
- 解决:重新做全量备份和同步。检查主库是否手动删除过 Binlog 文件而未通知从库。
-
大事务导致主从严重延迟
- 现象:
Seconds_Behind_Master飙升。 - 解决:MySQL 单线程回放 Binlog 是瓶颈。对于超大事务,建议在低峰期执行,或拆分为小事务。如果延迟持续无法恢复,考虑引入 MHA、Orchestrator 等自动化工具进行故障切换,而非手动修复。
- 现象:
-
字符集不一致
- 铁律:主从服务器的
character_set_server和collation_server必须完全一致,否则可能出现乱码或索引失效。
- 铁律:主从服务器的
六、 总结
安全配置 MySQL 主从的核心逻辑是:
- 网络隔离:仅限内网互访,禁用公网暴露。
- 权限最小化:专用复制账号,非 Root。
- 数据一致性:ROW 格式 + 严格的时间同步 + 正确的 Binlog Position 起点。
- 容错机制:启用半同步复制,配合完善的监控告警。
这套流程在阿里云 ECS、腾讯云 CVM 或 AWS EC2 上均通用。如果你的业务对数据零丢失有极高要求,建议在此基础上进一步评估是否引入 MGR(MySQL Group Replication)或 PXC(Percona XtraDB Cluster)等多主架构,但这会带来更高的运维复杂度,需根据实际场景权衡。
云技术博客