14.10.3 路由与读写分离不生效
路由与读写分离不生效通常由“规则未生效、匹配失败、会话被固定到写库、读库不可用”引起。建议先用最小化示例复现实验环境,再按顺序排查。
1) 规则是否加载到运行内存#
运行内存无规则时,路由不会生效。
-- 对比配置表与运行时
SELECT rule_id,active,match_pattern,regex,destination_hostgroup
FROM mysql_query_rules;
SELECT rule_id,active,match_pattern,regex,destination_hostgroup
FROM runtime_mysql_query_rules;
若 runtime 为空或缺失规则,执行加载与持久化:
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
验证:
SELECT COUNT(*) FROM runtime_mysql_query_rules;
预期:返回值大于 0。
2) 规则优先级与匹配条件#
rule_id 小优先,active=1 必须开启;match_pattern/regex 必须命中真实 SQL(注意大小写、空白、注释)。
示例:最小读写分离规则
DELETE FROM mysql_query_rules;
INSERT INTO mysql_query_rules
(rule_id, active, match_pattern, destination_hostgroup, apply)
VALUES
(10, 1, '^SELECT .*', 20, 1),
(20, 1, '^INSERT|^UPDATE|^DELETE|^REPLACE', 10, 1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
命令解释:
- rule_id: 规则优先级,越小越先匹配
- match_pattern: 正则匹配 SQL 语句
- destination_hostgroup: 路由目标组
- apply=1: 匹配即停止后续规则
验证命中:
SELECT * FROM stats_mysql_query_rules;
预期:hits 增长,且 destination_hostgroup 变为 20(读)或 10(写)。
3) 用户与默认主机组#
用户默认主机组错误会把所有请求固定到写库。
SELECT username,default_hostgroup,transaction_persistent
FROM mysql_users;
若 default_hostgroup 不是写组(通常 10),或 transaction_persistent=1 导致会话固定写库,调整示例:
UPDATE mysql_users
SET default_hostgroup=10, transaction_persistent=0
WHERE username='app';
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
4) 读库是否在线与健康检查#
读库不在线会导致读流量回落到写库。
SELECT hostgroup_id,hostname,status,weight,max_connections
FROM mysql_servers;
预期:读组(如 20)服务器 status=ONLINE。
查看健康检测:
SELECT * FROM stats_mysql_server_ping;
SELECT * FROM stats_mysql_replication_hostgroups;
若发现读库被标记 SHUNNED 或延迟超阈值,修复主从或调整阈值后再观察。
5) 会话行为导致固定写库#
事务会强制同一连接走写库。
-- 应用侧排查示例(MySQL 客户端)
SELECT @@autocommit; -- 0 会固定到写库
BEGIN; -- 开启事务
SELECT * FROM t1; -- 会走写库
COMMIT;
建议:业务显式区分读写连接,或使用连接池拆分读写。
6) 关键排错命令清单#
-- 命中统计
SELECT * FROM stats_mysql_query_rules;
-- 连接路由
SELECT * FROM stats_mysql_connections;
-- 归一化 SQL 与路由
SELECT * FROM stats_mysql_query_digest ORDER BY count_star DESC LIMIT 5;
7) 可执行排错脚本(逐步验证)#
#!/usr/bin/env bash
# 文件: /opt/proxysql/check_rw.sh
# 说明: 快速检查规则与读库状态
MYSQL="mysql -h127.0.0.1 -P6032 -uadmin -padmin -e"
$MYSQL "SELECT COUNT(*) AS runtime_rules FROM runtime_mysql_query_rules;"
$MYSQL "SELECT rule_id,active,match_pattern,destination_hostgroup FROM runtime_mysql_query_rules;"
$MYSQL "SELECT username,default_hostgroup,transaction_persistent FROM mysql_users;"
$MYSQL "SELECT hostgroup_id,hostname,status FROM mysql_servers;"
$MYSQL "SELECT * FROM stats_mysql_query_rules;"
运行:
bash /opt/proxysql/check_rw.sh
预期:runtime 规则非空,读库 ONLINE,命中统计有增长。
8) 实战练习#
- 在测试环境创建读写组(写=10,读=20),为读写组各加一台 MySQL。
- 添加上述读写规则并加载到 runtime。
- 通过 ProxySQL 发送
SELECT与INSERT,使用stats_mysql_connections验证路由。 - 手动把读库状态改为
OFFLINE_SOFT,观察读请求是否回落到写库。
练习命令示例:
UPDATE mysql_servers SET status='OFFLINE_SOFT'
WHERE hostgroup_id=20 AND hostname='10.0.0.2';
LOAD MYSQL SERVERS TO RUNTIME;
预期:SELECT 请求回落到写组。