MySQL主从倒换常见问题及构造手段
在MySQL主从架构中,主从切换(尤其是故障切换)可能因复制延迟、配置不当、网络问题等导致各种异常。以下是常见异常及对应的解决方法:
一、数据不一致(最常见)
异常表现
切换后,新主库(原从库)缺少主库宕机前的部分写入数据,或数据与原主库存在差异,导致业务数据丢失或冲突。
原因
- 主从复制延迟:从库未及时同步主库的binlog(如网络延迟、从库SQL线程阻塞),切换时从库数据落后。
- 主库未刷盘:主库宕机时,部分已提交的事务未写入binlog(如
sync_binlog=0
),从库无法同步。 - 复制过滤规则:主从配置了
binlog_do_db
/binlog_ignore_db
等过滤规则,导致部分数据未同步。
解决方法
-
切换前检查同步状态:
切换前通过show slave status
确认从库的Seconds_Behind_Master
为0(无延迟),且Slave_IO_Running
和Slave_SQL_Running
均为Yes
。
(若使用GTID,需确认从库的gtid_executed
包含主库的所有gtid_set
)。 -
减少复制延迟:
- 主库开启
sync_binlog=1
和innodb_flush_log_at_trx_commit=1
(确保事务提交后立即刷盘)。 - 从库关闭
binlog
(非必要时),或优化从库配置(如加大innodb_buffer_pool_size
),减少SQL线程阻塞。 - 采用半同步复制(
rpl_semi_sync_master_enabled=1
),确保主库事务至少被一个从库确认后再提交,降低数据丢失风险。
- 主库开启
-
避免不合理的复制过滤:
尽量不使用binlog_do_db
等过滤规则(易因库名大小写、默认库切换导致漏同步),如需过滤,改用replicate_do_table
(从库侧过滤)。 -
切换后数据校验:
用工具(如pt-table-checksum)对比新主库与原主库(恢复后)的数据差异,对缺失数据手动补写(需结合业务逻辑)。
二、从库无法提升为主库
异常表现
切换时,原从库无法被设置为新主库,报错如“无法开启binlog”“缺少复制权限”等。
原因
- 从库未开启binlog:从库
log_bin
参数未开启,或server_id
未配置(主库必须开启binlog)。 - 未开启
log_slave_updates
:从库未配置log_slave_updates=1
,导致其同步的事务未写入自身binlog,新从库无法同步。 - 缺少复制账号权限:新主库(原从库)未创建供其他从库连接的复制账号(
REPLICATION SLAVE
权限)。
解决方法
-
提前配置从库为主库的条件:
从库需满足:log_bin=ON
、server_id
唯一、log_slave_updates=1
(若需级联复制)。
(可在初始化从库时统一配置,避免切换时临时修改)。 -
预创建复制账号:
在所有从库上提前创建复制账号(如GRANT REPLICATION SLAVE ON *.* TO 'repl'@'xxx' IDENTIFIED BY 'pwd';
),确保切换后其他从库可连接新主库。 -
临时修复配置:
若未开启binlog,可临时修改my.cnf
并重启从库(但需注意重启时间对业务的影响);若log_slave_updates
未开启,切换后新从库可能无法同步历史数据,需重新搭建复制。
三、脑裂(双主并存)
异常表现
切换后,原主库未被正确下线,仍接受业务写入,而新主库也在处理写入,导致两个主库数据分歧(“脑裂”),后续无法合并。
原因
- 切换工具未隔离旧主库:手动切换或工具(如MHA)故障,未关闭原主库的写入端口(如3306)。
- 网络分区:原主库与集群网络隔离,但仍能接收部分客户端请求(如客户端直连IP)。
解决方法
-
自动隔离旧主库:
- 用VIP(虚拟IP)绑定主库,切换时将VIP漂移到新主库,同时通过脚本关闭旧主库的
mysqld
进程或防火墙拦截3306端口。 - 工具层面:MHA默认会通过
ssh
杀死旧主库的mysqld
进程(需配置kill_old_master=1
)。
- 用VIP(虚拟IP)绑定主库,切换时将VIP漂移到新主库,同时通过脚本关闭旧主库的
-
业务层限制写入:
应用连接数据库时强制通过VIP或域名,避免直连IP;配置短TTL的DNS,确保切换后快速指向新主库。 -
检测双主状态:
监控工具(如Prometheus)定期检查集群中是否存在多个read_only=OFF
的节点,发现双主时自动锁定旧主库(set global read_only=1
)。
四、复制线程异常(切换后新主从复制中断)
异常表现
切换后,其他从库连接新主库时,IO线程或SQL线程报错(如“找不到binlog文件”“GTID集合不匹配”)。
原因
- binlog位置丢失:原从库提升为主库后,其他从库的复制起点(
MASTER_LOG_FILE
/MASTER_LOG_POS
)在新主库中不存在(如新主库binlog被清理)。 - GTID冲突:若使用GTID,新主库的
gtid_executed
与其他从库的gtid_executed
存在交集但不完整,导致复制报错“GTID already exists”。 - 权限或网络问题:新主库防火墙拦截、复制账号密码错误,导致IO线程连接失败。
解决方法
-
正确设置复制起点:
切换后,其他从库需以新主库当前的binlog位置(show master status
)为起点重新配置复制(CHANGE MASTER TO ...
)。
(若用GTID,可通过SET GLOBAL gtid_purged = 新主库的gtid_executed
后,START SLAVE
自动同步)。 -
合理保留binlog:
主库(包括潜在主库)配置expire_logs_days
(或binlog_expire_logs_seconds
)保留足够长时间的binlog(如7天),避免切换时binlog被提前清理。 -
修复GTID一致性:
若GTID冲突,可在从库执行RESET SLAVE ALL
清除旧GTID信息,再重新基于新主库的GTID配置复制(需确保新主库包含从库需要的所有事务)。 -
检查网络与权限:
确认新主库3306端口可被其他从库访问,复制账号密码正确且权限有效(REPLICATION SLAVE
)。
五、应用连接切换失败
异常表现
切换后,应用无法连接新主库,报错“连接超时”“拒绝连接”,导致业务中断。
原因
- 连接池未刷新:应用连接池缓存了旧主库的连接,未及时切换到新主库IP/VIP。
- VIP漂移失败:VIP未成功绑定到新主库(如ARP广播失败、网络设备配置限制)。
- DNS缓存:应用依赖DNS解析主库地址,DNS TTL过长,未及时更新到新主库IP。
解决方法
-
优化连接池配置:
应用连接池设置短连接超时时间(如maxWait=1000ms
),并在切换后主动触发连接池刷新(如调用closeIdleConnections
)。 -
确保VIP漂移可靠:
使用成熟的VIP管理工具(如keepalived
),配置nopreempt
避免抢占,同时在切换脚本中检查VIP绑定状态(ip addr
),失败则重试。 -
减少DNS缓存影响:
配置DNS TTL为秒级(如60秒),或应用层使用本地DNS缓存刷新机制(如定时重新解析)。
六、新主库性能不足
异常表现
切换后,新主库(原从库)因写入压力骤增,出现CPU/IO使用率过高、响应延迟等性能问题。
原因
- 从库配置低于主库:从库硬件(CPU、内存、磁盘)或参数(如
innodb_buffer_pool_size
)配置较弱,无法承受主库的写入压力。 - 从库有额外负载:从库同时承担只读查询或备份任务,切换后写入+查询导致资源竞争。
解决方法
-
主从配置一致化:
确保从库与主库硬件规格、MySQL参数(如innodb_flush_log_at_trx_commit
、max_connections
)一致,避免“小马拉大车”。 -
切换前清理从库负载:
切换前暂停从库的只读查询(如关闭业务只读路由)、备份任务,确保资源集中用于处理写入。 -
临时扩容:
若性能不足,可临时增加新主库的资源(如升级云服务器规格),或通过读写分离将部分查询分流到其他从库。
总结
主从切换的异常多源于“准备不足”或“过程失控”。核心解决思路是:
- 切换前:确保从库配置合规、数据同步完成、负载清理完毕;
- 切换中:依赖自动化工具(如MHA、Orchestrator)减少人为操作,严格隔离旧主库;
- 切换后:校验数据一致性、监控新主库状态、快速修复复制问题。
通过提前演练和完善监控,可大幅降低异常概率。
测试MySQL云数据库的自愈能力时,需构造各类可能导致主从异常、服务中断的场景,观察云数据库是否能自动检测异常、恢复服务(如主从切换、进程重启、数据修复等),并最终保证数据一致性和可用性。以下是常见异常场景的构造方法,需在隔离的测试环境中执行(避免影响生产):
一、主库故障场景(核心自愈场景)
主库故障是最常见的高可用挑战,云数据库通常需自动将从库提升为主库,恢复写入能力。
1. 主库进程崩溃
- 构造方法:通过
kill -9
强制终止主库的mysqld
进程,或使用工具触发进程异常退出(如发送SIGSEGV
信号模拟段错误)。
示例:ps -ef | grep mysqld | grep -v grep | awk '{print $2}' | xargs kill -9
- 预期自愈:云数据库监控(如
keepalived
、MGR
的故障检测)应在秒级内发现主库进程死亡,自动将健康从库切换为主库,并更新VIP/域名指向新主库。
2. 主库服务器宕机
模拟主库所在物理机/虚拟机故障(如断电、系统崩溃)。
- 构造方法:
- 虚拟机环境:直接关闭主库所在VM(
virsh destroy [vm-name]
)或强制断电。 - 容器环境:删除主库容器(
docker rm -f [container-name]
)。
- 虚拟机环境:直接关闭主库所在VM(
- 预期自愈:监控检测到主库节点完全失联(网络不通、心跳中断),触发主从切换,新主库接管服务,同时可能自动在新节点重建从库(若配置了自动扩缩容)。
3. 主库磁盘故障
模拟主库磁盘不可用(如只读、满盘、损坏),导致无法写入binlog或数据。
- 构造方法:
- 磁盘满:用
dd
命令创建大文件填满主库数据目录所在磁盘(dd if=/dev/zero of=/data/fill.disk bs=1G count=100
,直到磁盘使用率100%)。 - 磁盘只读:通过
mount -o remount,ro /data
将数据目录挂载为只读。
- 磁盘满:用
- 预期自愈:主库因无法写入binlog或数据而异常,监控检测到后触发切换,新主库需保证切换前的binlog已同步到从库(避免数据丢失)。
二、从库故障场景
从库故障可能影响读服务或主从同步,云数据库需自动修复从库(如重建、切换备用从库)。
1. 从库同步中断(IO/SQL线程异常)
模拟从库无法同步主库binlog(如IO线程中断、SQL线程报错)。
- 构造方法:
- 手动停止从库IO线程:
stop slave io_thread;
(导致无法拉取主库新binlog)。 - 制造SQL线程冲突:在从库手动写入与主库冲突的数据(如插入相同主键的记录),再执行
start slave;
,此时SQL线程会因主键冲突报错停止。
- 手动停止从库IO线程:
- 预期自愈:云数据库应检测到从库同步中断,自动尝试重启线程(
start slave;
);若无法恢复(如数据冲突),可能自动重建从库(基于新主库的全量备份+binlog增量同步)。
2. 从库服务器宕机
模拟从库节点故障,影响读负载分担或主从切换的备选节点。
- 构造方法:同主库宕机(关闭从库VM/容器)。
- 预期自愈:监控发现从库失联后,自动在新节点重建从库(基于当前主库的数据),恢复主从架构的冗余能力。
三、网络异常场景
网络问题可能导致主从通信中断、脑裂等,考验云数据库的网络容错能力。
1. 主从网络中断(分区)
模拟主从节点之间的网络断开,导致同步失败。
- 构造方法:
- 用
iptables
屏蔽主从通信端口(3306):在主库或从库执行iptables -A INPUT -p tcp --dport 3306 -j DROP
(阻断对方连接)。 - 用
tc
工具模拟网络丢包/延迟:tc qdisc add dev eth0 root netem loss 100%
(100%丢包,完全断连)。
- 用
- 预期自愈:
- 若短暂断连:网络恢复后,从库应自动重连主库并继续同步(需支持binlog断点续传)。
- 若长时间断连:云数据库可能判定主库“假死”(需结合脑裂防护机制),避免误切换;若主库确实故障,才触发切换。
2. 脑裂(双主冲突)
模拟主从都认为自己是主库,导致双写数据冲突(最危险的网络异常场景)。
- 构造方法:
- 先阻断主从网络(如
iptables
屏蔽),再手动将从库提升为主库(stop slave; reset slave all;
),同时主库仍在接受写入(此时双主并存)。 - 恢复网络后,双主同时写入相同表的相同主键,触发数据冲突。
- 先阻断主从网络(如
- 预期自愈:云数据库需通过脑裂防护机制(如Quorum投票、分布式锁、VIP唯一性)避免双主,若已发生冲突,应能检测到数据不一致并通过预设策略处理(如以原主库数据为准,或告警人工介入)。
四、资源耗尽场景
主库/从库因资源不足(内存、CPU)导致服务降级或崩溃,考验资源自愈能力。
1. 主库内存溢出(OOM)
模拟主库因内存不足被系统杀死。
- 构造方法:在主库执行大量占用内存的操作,如
select * from large_table into outfile ...
(全表扫描+大结果集),或创建大量MEMORY
引擎表并插入数据,直到触发系统OOM(echo 1 > /proc/sys/vm/overcommit_memory
可加速OOM)。 - 预期自愈:主库进程被OOM杀死后,监控触发主从切换;同时云数据库应限制单语句内存使用(如
max_heap_table_size
),避免频繁OOM。
2. CPU耗尽
模拟主库因CPU占用100%导致无法响应请求。
- 构造方法:在主库所在服务器执行大量CPU密集型任务(如
for i in {1..100}; do dd if=/dev/zero of=/dev/null & done
),使CPU使用率长期维持100%。 - 预期自愈:监控检测到主库响应延迟(如
ping
超时、连接超时),触发主从切换;同时可能自动限制异常进程的CPU使用(如cgroup)。
五、配置/数据异常场景
模拟因配置错误或数据损坏导致的服务异常。
1. 主库binlog损坏
模拟主库binlog文件损坏,导致从库同步失败。
- 构造方法:直接编辑主库的binlog文件(如
vi /data/mysql/binlog.000001
),手动修改内容破坏格式,再执行flush logs;
让主库切换到新binlog,此时从库拉取旧binlog会因格式错误中断。 - 预期自愈:云数据库应检测到binlog损坏,自动清理损坏的binlog(若已同步到从库),或从备份恢复binlog,确保从库可继续同步。
2. 权限配置错误
模拟主从同步账号权限丢失,导致从库无法连接主库。
- 构造方法:在主库删除从库同步账号(
drop user 'repl'@'slave-ip'; flush privileges;
)。 - 预期自愈:从库IO线程因权限不足中断,云数据库应自动重建同步账号(通过预设配置),或重启从库同步并使用备用账号。
测试注意事项
- 环境隔离:所有操作必须在测试环境执行,避免影响生产数据。
- 回滚预案:提前备份主从数据,准备手动恢复流程(若自愈失败)。
- 指标监控:记录自愈时间(从异常发生到服务恢复的时长)、数据一致性(切换后主从数据是否一致)、服务可用性(切换期间是否断连)。
- 场景组合:尝试混合场景(如主库宕机+从库同步延迟),验证云数据库在复杂故障下的自愈能力。
通过以上场景的构造,可全面验证MySQL云数据库在各类异常下的自动检测、切换、修复能力,确保高可用机制可靠有效。