14.6.8 常见故障与切换失败排查
在ProxySQL负载均衡与故障切换场景中,切换失败通常由健康检查误判、后端状态同步异常、用户连接与事务状态、以及与外部高可用组件联动不一致引起。本节给出原理草图、排查路径、可执行命令、示例配置与练习,帮助快速定位与验证修复效果。
一、原理草图:切换路径与状态流转
二、常见故障现象(带示例)
- 后端已宕机但仍被选中:请求超时、连接卡住
# 客户端超时示例:应用日志中出现
# ERROR 2003 (HY000): Can't connect to MySQL server on '10.0.0.11' (110)
- 后端恢复后未回切:节点状态一直为OFFLINE_SOFT或SHUNNED
SELECT hostgroup_id, hostname, status FROM runtime_mysql_servers;
-- 预期恢复为 ONLINE,实际为 SHUNNED
- 读写分离错配:写流量打到只读从库
SELECT * FROM stats_mysql_query_digest
WHERE digest_text LIKE 'insert%';
-- 预期: hostgroup=写库,实际: hostgroup=读库
三、排查与修复的命令清单(含解释)
1. 运行态与配置态一致性
-- 运行态(真实生效)
SELECT hostgroup_id, hostname, port, status, weight
FROM runtime_mysql_servers;
-- 配置态(磁盘配置)
SELECT hostgroup_id, hostname, port, status, weight
FROM mysql_servers;
-- 将配置加载到运行态并保存
LOAD MYSQL SERVERS TO RUNTIME; -- 立即生效
SAVE MYSQL SERVERS TO DISK; -- 持久化
- 健康检查日志与失败原因
SELECT * FROM mysql_server_ping_log
ORDER BY time_start_us DESC LIMIT 10;
SELECT * FROM mysql_server_connect_log
ORDER BY time_start_us DESC LIMIT 10;
- 关键字段解释:
errcode/errmsg指示超时、认证失败或拒绝连接。
- 路由规则与优先级
SELECT rule_id, active, match_pattern, destination_hostgroup, apply
FROM mysql_query_rules
ORDER BY rule_id ASC;
- 说明:
rule_id越小优先级越高,apply=1表示命中后继续匹配。
- 连接池与资源瓶颈
SELECT hostgroup, srv_host, ConnUsed, ConnFree, MaxConnUsed, Queries
FROM stats_mysql_connection_pool;
- 解释:
ConnUsed/ConnFree反映连接池是否饱和,MaxConnUsed用于判断是否需要扩容。
四、切换失败的典型原因与可执行处理
1. 健康检查阈值不合理(误切换/不切换)
-- 查看监控参数
SELECT * FROM global_variables
WHERE variable_name LIKE 'mysql-monitor%';
-- 示例调优(根据网络抖动调整)
SET mysql-monitor_connect_timeout = 2000;
SET mysql-monitor_ping_interval = 2000;
SET mysql-monitor_ping_max_failures = 3;
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
- 后端状态未同步到运行态
-- 配置态已改,运行态未生效
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
- 节点被SHUNNED后无法恢复
-- 手动恢复
UPDATE mysql_servers
SET status='ONLINE'
WHERE hostname='10.0.0.12' AND hostgroup_id=20;
LOAD MYSQL SERVERS TO RUNTIME;
- 读写分离规则冲突
-- 示例:明确写规则优先级更高
INSERT INTO mysql_query_rules
(rule_id,active,match_pattern,destination_hostgroup,apply)
VALUES
(10,1,'^select',20,1),
(5,1,'^(insert|update|delete|replace)',10,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
- 事务粘性导致切换不生效
-- 示例:查看事务粘性策略
SELECT * FROM global_variables
WHERE variable_name='mysql-autocommit_false_is_transaction';
-- 建议:应用侧避免长事务,必要时强制提交/回滚后重建连接
- 网络与DNS问题
# 连通性检查
ping -c 3 10.0.0.12
nc -vz 10.0.0.12 3306
# DNS解析一致性
dig +short mysql-master.example.com
五、与外部HA组件联动排查(含回调脚本示例)
- 回调未触发或权限不足导致ProxySQL未更新主库
# /opt/ha/callbacks/update_proxysql.sh
#!/usr/bin/env bash
set -e
PROXYSQL_ADMIN="mysql -h 127.0.0.1 -P6032 -uadmin -padmin"
NEW_MASTER_IP="$1"
$PROXYSQL_ADMIN <<'SQL'
DELETE FROM mysql_servers WHERE hostgroup_id=10;
SQL
$PROXYSQL_ADMIN <<SQL
INSERT INTO mysql_servers(hostgroup_id,hostname,port,status,weight)
VALUES(10,'${NEW_MASTER_IP}',3306,'ONLINE',100);
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
SQL
# 预期效果:运行态写Hostgroup指向新主库
mysql -h127.0.0.1 -P6032 -uadmin -padmin -e \
"SELECT hostgroup_id,hostname,status FROM runtime_mysql_servers WHERE hostgroup_id=10;"
六、可复现的故障演练与验证步骤
1. 演练:模拟主库故障
# 在主库执行(示例)
sudo systemctl stop mysqld
- 观察:ProxySQL状态变化
SELECT hostname, status FROM runtime_mysql_servers WHERE hostgroup_id=10;
-- 预期:主库变为 OFFLINE_SOFT/SHUNNED
- 恢复:重启主库并回切
sudo systemctl start mysqld
-- 手动回切(如未自动回切)
UPDATE mysql_servers
SET status='ONLINE'
WHERE hostgroup_id=10 AND hostname='10.0.0.11';
LOAD MYSQL SERVERS TO RUNTIME;
七、排错流程(最短路径)
1. 识别故障范围:客户端错误类型与Hostgroup影响范围
2. 校验健康检查:查看ping/connect日志定位失败原因
3. 对比配置态与运行态:排除未加载
4. 验证路由规则:检查规则优先级与匹配范围
5. 分析连接池状态:定位资源瓶颈
6. 小流量验证修复:再逐步放量
7. 记录与复盘:形成参数与告警优化建议
八、练习题(含预期结果)
1. 将写Hostgroup的主库切换到10.0.0.13,并验证运行态是否生效。
- 预期:runtime_mysql_servers 中 hostgroup_id=10 仅显示 10.0.0.13 为 ONLINE。
2. 创建一条规则,使SELECT ... FOR UPDATE走写库。
- 预期:stats_mysql_query_digest 中该语句命中写Hostgroup。
3. 调整健康检查参数,使ping超时时间为1秒、最大失败次数为2,并保存生效。
- 预期:global_variables 中参数已更新且重启后仍保留。