proxysql + mysql 8.0 读写分离在生产环境可行,但须强制用户使用 mysql_native_password 插件或升级 proxysql 至 2.4+,严格依赖 mgr 状态自动分组 hostgroup,并配置 transaction_persistent=1 和 replication_lag 检测以保障路由正确与数据时效。

直接上结论:ProxySQL + MySQL 8.0 读写分离在生产环境可行,但必须绕开 mysql_native_password 认证兼容性陷阱,并严格按 hostgroup 角色划分节点状态,否则路由会失效或连接被拒。
MySQL 8.0 用户认证必须显式降级为 caching_sha2_password 或适配 ProxySQL 2.4+
MySQL 8.0 默认使用 caching_sha2_password 插件,而 ProxySQL 2.3.x 及更早版本仅支持 mysql_native_password。若未处理,会出现 Access denied for user 'rw'@'192.168.x.x' (using password: YES) 错误,即使密码正确。
- 方案一(推荐):创建用户时强制指定插件:
CREATE USER 'rw'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; - 方案二:升级 ProxySQL 至 2.4+(如 2.6.3 或 2.7.3),它原生支持
caching_sha2_password,但需确认你的监控用户(monitor)也用同种插件,否则mysql-monitor_username登录失败会导致节点状态无法自动识别 - 切勿依赖
default_authentication_plugin全局配置——ProxySQL 不读取该变量,只认用户级别的plugin字段
hostgroup 分组不能靠手动 INSERT,必须依赖 MGR 状态自动同步
手动把所有节点塞进 reader_hostgroup = 30 是常见错误。MGR 集群中只有 PRIMARY 节点可写,其余为 SECONDARY(只读),而 ProxySQL 的 mysql_server_group_replication_checker 脚本依赖 sys.gr_member_routing_candidate_status 视图判断角色。若跳过该机制,写请求可能发到只读节点,触发 ERROR 1290 (HY000): The MySQL server is running with the --read-only option。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 初始插入必须全进
offline_hostgroup = 40,再通过LOAD MYSQL SERVERS TO RUNTIME触发自动探测 - 确保 MySQL 侧已安装
SYSschema(MySQL 8.0 默认自带),且监控用户有SELECT权限:GRANT SELECT ON sys.* TO 'monitor'@'%'; - 检查自动分组结果:
SELECT hostgroup_id, hostname, status FROM mysql_servers;—— 正常应看到 PRIMARY 落入writer_hostgroup = 10,SECONDARY 自动归入reader_hostgroup = 30
读写分离规则要避开隐式事务和 SELECT ... FOR UPDATE
ProxySQL 默认按语句前缀(SELECT / INSERT 等)路由,但 SELECT ... FOR UPDATE 或隐式开启事务后的 SELECT 若被错误发往从库,会因从库只读报错;反之,纯 SELECT 发到主库又浪费资源。
- 最简方案:启用
transaction_persistent = 1(在mysql_query_rules中),让同一事务内所有语句固定路由到首个节点 - 关键规则示例:
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (1, 1, '^SELECT.*FOR UPDATE', 10, 1);
强制带锁查询走写组 - 避免用
match_pattern写模糊正则——MySQL 8.0 的 JSON 函数、窗口函数等语法易导致匹配失效;优先用match_digest(基于解析后 AST)
监控与故障切换的延迟阈值必须调低
MGR 的 replication_lag 在 ProxySQL 中默认不启用,若不显式配置,从库即使延迟数分钟仍会被认为“健康”,导致读到过期数据。
- 启用延迟检测:
UPDATE global_variables SET variable_value='true' WHERE variable_name='mysql-monitor_enabled';,再LOAD MYSQL VARIABLES TO RUNTIME; - 设置最大容忍延迟(单位秒):
UPDATE mysql_servers SET max_replication_lag=5 WHERE hostgroup_id=30;—— 超过 5 秒自动移出reader_hostgroup - 验证是否生效:
SELECT * FROM monitor.mysql_server_replication_lag_log ORDER BY time_start_us DESC LIMIT 3;,看日志里是否有非零 lag 值
真正难的不是配通,而是让 ProxySQL 看懂 MGR 的角色切换节奏——它不依赖 MySQL 的 read_only 变量,而依赖 sys.gr_member_routing_candidate_status 的实时快照。任何跳过这个视图、试图用脚本轮询 SHOW STATUS LIKE 'wsrep_local_state'(那是 Galera)的做法,在 MGR 场景下都会失效。










