原文DB ID: 130
来源: https://www.henghost.com/news/article/63512/
一、为什么需要MySQL主备自动切换?
在生产环境中,数据库是整个系统最核心的组件。一旦主数据库(Master)发生宕机、网络故障或硬件损坏,如果依赖人工介入切换从库,整个恢复过程可能耗时数小时,期间业务完全瘫痪。
主备自动切换(Master-Slave Failover) 能让系统在检测到主库故障后,自动将一个健康的从库(Slave)提升为新的主库,并将流量切换过去,实现真正的无人值守高可用。
二、整体架构一览
| 组件 | 作用 | 关键配置 |
|---|---|---|
| 主数据库(Master) | 接收所有写操作 | 开启 binary log |
| 从数据库(Slave) | 实时同步主库数据 | 配置 relay log |
| 健康检测脚本 | 监控主从库状态 | 心跳 + 阈值判断 |
| 自动切换脚本 | 执行故障转移 | 提升从库 + 更新连接 |
| 负载均衡器(可选) | 统一入口,分发流量 | 健康检查 + 故障转移 |
三、详细配置步骤
步骤1:配置主从复制(MySQL Replication)
主库配置:
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = Row
在主库上创建复制账号:
CREATE USER 'repl'@'%' IDENTIFIED BY 'StrongPassword';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
从库配置:
[mysqld]
server-id = 2
relay-log = relay-bin
read-only = ON
执行主从连接:
CHANGE MASTER TO
MASTER_HOST = '主库IP',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'StrongPassword',
MASTER_LOG_FILE = 'mysql-bin.000001',
MASTER_LOG_POS = 154;
START SLAVE;
💡 小贴士:生产环境中建议至少配置 2个从库,一主一从做高可用,另一个做跨机房灾备。
步骤2:部署健康监控
推荐使用 MHA(MySQL High Availability) 或自建脚本结合 Prometheus + Grafana:
#!/bin/bash
# check_master_health.sh
MASTER_IP="192.168.1.10"
SLAVE_IP="192.168.1.11"
# 检测主库连通性
if ! mysqladmin ping -h $MASTER_IP --silent; then
echo "主库不可达,触发切换流程"
# 触发切换脚本
bash /opt/scripts/mysql_failover.sh
fi
建议监控指标:
- ✅ MySQL 进程存活状态
- ✅ 主从复制延迟(
Seconds_Behind_Master) - ✅ 二进制日志传输状态(
Slave_IO_Running/Slave_SQL_Running) - ✅ 磁盘 I/O 和 CPU 使用率
- ✅ 连接数是否超限
步骤3:编写自动切换脚本
#!/usr/bin/env python3
# mysql_failover.py
import pymysql
import subprocess
import logging
from datetime import datetime
logging.basicConfig(filename='/var/log/mysql_failover.log', level=logging.INFO)
def check_slave_health(host, port=3306):
"""检查从库是否适合被提升"""
try:
conn = pysysql.connect(host=host, port=port, user='root', password='xxx')
cursor = conn.cursor()
cursor.execute("SHOW SLAVE STATUS")
status = cursor.fetchone()
conn.close()
# 判断条件:复制延迟小于5秒,IO和SQL线程都在运行
if status and status[32] == 'Yes' and status[33] == 'Yes' and status[37] < 5:
return True
return False
except Exception as e:
logging.error(f"检查从库 {host} 失败: {e}")
return False
def promote_slave(slave_ip):
"""将指定从库提升为新的主库"""
logging.info(f"{datetime.now()} - 开始提升从库 {slave_ip}")
# 1. 停止主从复制
conn = pymysql.connect(host=slave_ip, port=3306, user='root', password='xxx')
cursor = conn.cursor()
cursor.execute("STOP SLAVE")
cursor.execute("RESET SLAVE ALL")
# 2. 取消只读限制
cursor.execute("SET GLOBAL read_only = OFF")
cursor.execute("SET GLOBAL super_read_only = OFF")
conn.close()
# 3. 更新其他从库指向新主库
# ...(根据实际情况配置)
logging.info(f"从库 {slave_ip} 已成功提升为新主库")
return True
# 主逻辑
if __name__ == '__main__':
candidate_slaves = ['192.168.1.11', '192.168.1.12']
for slave in candidate_slaves:
if check_slave_health(slave):
promote_slave(slave)
break
步骤4:配置负载均衡器(推荐方案)
使用 HAProxy 作为数据库代理,统一入口并做健康检查:
listen mysql-cluster
bind 0.0.0.0:3306
mode tcp
balance roundrobin
option mysql-check user healthcheck
server master 192.168.1.10:3306 check inter 2000 rise 2 fall 3
server slave1 192.168.1.11:3306 check inter 2000 rise 2 fall 3 backup
server slave2 192.168.1.12:3306 check inter 2000 rise 2 fall 3 backup
步骤5:使用自动化工具管理配置
推荐使用 Ansible 来批量管理主从配置,保证一致性:
# mysql_master_slave.yml
- hosts: mysql_servers
become: yes
tasks:
- name: 配置MySQL主从复制
template:
src: my.cnf.j2
dest: /etc/my.cnf
notify: 重启MySQL
- name: 配置复制账号
mysql_user:
name: repl
password: "{{ repl_password }}"
priv: "*.*:REPLICATION SLAVE"
state: present
步骤6:充分的测试与演练
⚠️ 重要:高可用方案不做演练就上线,等于没有方案!
建议每月执行一次模拟故障演练:
- 模拟主库宕机(
kill -9 mysqld) - 观察自动切换是否在预期时间内完成(建议 < 30秒)
- 验证数据无丢失(对比
Relay_Master_Log_File与原主库 position) - 确认应用层连接自动恢复
- 恢复原主库,将其降级为从库重新加入集群
步骤7:完善文档与故障恢复策略
必须文档化的内容:
- 各服务器 IP、端口、角色说明
- 自动切换触发条件和阈值
- 手动干预的紧急操作步骤
- 切换后的验证检查清单
- 数据一致性校验方法
四、安全性注意事项
| 安全措施 | 说明 |
|---|---|
| 网络隔离 | 主从库之间使用内网,不对外暴露 |
| 访问控制 | 最小权限原则,禁止应用直接用 root 连接 |
| 加密连接 | 生产环境务必开启 SSL 加密的主从复制 |
| 定期更换密码 | 使用 Ansible Vault 管理敏感凭据 |
| 操作审计 | 开启 MySQL Audit Log,记录所有DDL操作 |
五、总结
MySQL 主备自动切换是云服务器数据库高可用架构的核心能力。通过合理配置主从复制、部署可靠的健康监控、编写健壮的切换脚本,并配合定期的演练和文档维护,可以实现:
- 🔄 故障自动恢复:主库宕机后30秒内自动切换
- 📉 业务零中断:配合负载均衡器实现无缝故障转移
- 🛡️ 数据安全保障:多从库架构防止数据丢失
如果您在配置过程中遇到任何问题,欢迎在评论区留言交流!