proxysql是最稳的mysql读写分离中间件选型,因其对应用零侵入、不改sql、不升级sdk,适合已上线系统快速接入;相比mycat和shardingsphere-jdbc更轻量可控,但配置需严格遵循规则:如设置weight、启用mysql_replication_hostgroups、reload query rules、从库read_only=1,且mysql_servers变更后须save+load才生效。

MySQL 本身不支持自动读写分离,必须靠外部组件或代码层显式控制路由。直接在单实例上改配置、加参数是无效的。
为什么 ProxySQL 是最稳的中间件选型
它对应用零侵入,不改 SQL、不升级 SDK,适合已上线系统快速接入;相比 MyCat(需适配分片语法)和 ShardingSphere-JDBC(耦合 Spring 生命周期),ProxySQL 更轻量、更可控。
但配置极易出错,常见问题包括:
-
mysql_servers表里没设weight,导致所有读流量打到同一台从库 -
mysql_replication_hostgroups没启用,ProxySQL 不识别从库为可读节点 - 改完
mysql_query_rules后忘记执行RELOAD MYSQL QUERY RULES,规则压根不生效 - 从库未设置
read_only = 1,ProxySQL 默认跳过该节点(它只认read_only=ON的实例为 slave)
路由规则怎么写才安全
规则匹配靠 match_digest 字段,优先级按 rule_id 升序执行。写法不当会导致误判,比如把 INSERT SELECT 当成纯读请求路由到从库。
实操建议:
- 读规则用
^SELECT开头,比只写SELECT更精准,避免匹配到含 SELECT 的 DML - 写规则必须覆盖
^INSERT、^UPDATE、^DELETE、^REPLACE、^ALTER等,不能漏掉 DDL - 事务内所有语句应强制走主库:加一条
match_digest = ^BEGIN|^START TRANSACTION,destination_hostgroup = writer_hostgroup - 高一致性读场景(如刚注册查资料),用注释标记:
/*+ USE_MASTER */ SELECT ...,再配一条规则提取该 hint
从库延迟大时怎么兜底
主从同步是异步的,延迟几秒甚至几十秒都可能发生。业务上不是所有读都能容忍旧数据——支付成功后查订单状态、后台审核后查结果,这类必须读主库。
不能依赖“sleep 几秒再读”这种野路子,也不该全量切回主库(否则读写分离失效)。真实可行的做法是:
- 监控
Seconds_Behind_Master,超过阈值(如 3s)时,ProxySQL 自动将该从库status = OFFLINE_HARD - 对关键接口,在应用层加
@Transactional(readOnly = true)+ 自定义注解,触发强制走主库逻辑 - 用
stats_mysql_connection_pool表查实际连接分布,别只信SHOW POOLS—— 后者只显示配置,前者才反映真实流量去向
最容易被忽略的是:ProxySQL 的 mysql_servers 表变更不会自动同步到运行时,必须执行 SAVE MYSQL SERVERS TO DISK 和 LOAD MYSQL SERVERS TO RUNTIME 才真正生效。漏掉任一环节,重启后配置就丢了。











