主从复制延迟导致读取旧数据,需启用半同步复制、避免写后立即查、强一致场景强制走主库;proxysql规则按rule_id升序匹配,高优先级读应前置;从库负载不均需动态权重调整;缓存与读写分离须明确分工边界。

主从复制延迟直接影响读一致性
从库跟不上主库,SELECT 就可能读到旧数据。这不是 ProxySQL 或应用层能绕开的底层限制。
- 优先启用
semisync(半同步复制):在主库配置中设置rpl_semi_sync_master_enabled=1,从库配rpl_semi_sync_slave_enabled=1,至少一个从库确认接收 binlog 后主库才返回,把延迟从秒级压到毫秒级 - 避免在写后立刻查——尤其不能依赖
SLEEP(0.1)这类硬等待,它不可靠且浪费连接;改用SELECT MASTER_POS_WAIT()或监听SHOW SLAVE STATUS中的Seconds_Behind_Master值 - 对强一致场景(如订单创建后立即查详情),直接在 SQL 中加注释提示路由:例如
/* FORCE_MASTER */ SELECT ...,要求 ProxySQL 或客户端 SDK 强制走主库
ProxySQL 的规则匹配顺序和正则陷阱
mysql_query_rules 表不是“先匹配就执行”,而是按 rule_id 升序扫描,第一条 active=1 且匹配成功的规则生效。顺序错了,SELECT 就可能被误判为写请求。
- 必须把高优先级规则(如带
FOR UPDATE、LOCK IN SHARE MODE的读)放在前面:INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (1, 1, '^SELECT.*FOR UPDATE$', 10, 1) -
^SELECT会匹配所有以 SELECT 开头的语句,但也会误伤SELECT ... INTO OUTFILE或存储过程中的SELECT——如果业务里有这类操作,得单独加规则排除 - 别忽略大小写:MySQL 默认不区分大小写,但 ProxySQL 的正则默认区分。加
i标志更稳妥,比如'(?i)^select'
从库负载不均导致部分节点过热
默认轮询或随机分发读请求,但不同从库硬件性能、网络延迟、慢查询堆积程度不同,容易出现“一个从库 CPU 95%,另两个才 30%”。
- ProxySQL 支持基于监控指标的动态权重:开启
monitor模块后,它会定期执行SELECT 1并记录响应时间,自动降低响应慢节点的weight值 - 手动调权时,不要只看 CPU,更要关注
Threads_running和Innodb_row_read——前者反映并发压力,后者暴露是否被大表扫描拖垮 - 禁止把所有从库都放进同一个
hostgroup:如果某从库因维护需要下线,max_replication_lag设置不当会导致 ProxySQL 仍尝试发请求过去,触发超时重试,放大延迟
缓存层与读写分离的协同边界
Redis 缓存和从库读取不是简单“二选一”,而是存在明确分工边界。混用反而增加一致性风险。
- 高频、不变或弱一致性要求的数据(如城市列表、开关配置)走
Caffeine本地缓存,绕过数据库层 - 结果集较大、更新频繁但允许几秒延迟的数据(如商品销量、评论数)用 Redis 缓存
SELECT结果,但必须配合双删策略:写库前删缓存 + 写库后延时再删一次 - 绝不缓存带
WHERE条件的动态查询结果——除非你实现了完整的 key 拆分和失效逻辑,否则极易缓存污染
真正卡住性能的,往往不是代理怎么配,而是主从之间那几百毫秒的 gap、规则表里第 3 条和第 4 条的顺序、某个从库上没 kill 掉的长事务。这些点不盯死,加再多从库也没用。











