MySQL 高可用系列 · Orchestrator + ProxySQL 第三篇——核心原理精讲

连接池、读写分离与查询路由机制

  • 三大设计原则:零重启改配置、事件驱动、协议感知
  • 连接池多路复用:一个后端连接服务多个前端会话
  • hostgroup 机制:写组 / 读组 / 路由规则三层
  • 读写分离核心:for update 走主库,普通 select 走从库
  • 配置三态分离:RUNTIME / MEMORY / DISK
  • 健康检查、用户管理、查询缓存与查询重写

流量闸门的内部机制

目 录

回顾与导读:从"大脑"到"闸门"

[第一章 ProxySQL 整体架构与三大设计原则](#第一章 ProxySQL 整体架构与三大设计原则)

[1.1 架构概览](#1.1 架构概览)

[1.2 三大设计原则](#1.2 三大设计原则)

[第二章 连接池:多路复用的魔法](#第二章 连接池:多路复用的魔法)

[2.1 为什么需要连接池](#2.1 为什么需要连接池)

[2.2 多路复用(Multiplexing)](#2.2 多路复用(Multiplexing))

[第三章 hostgroup:读写分离的基石](#第三章 hostgroup:读写分离的基石)

[3.1 hostgroup 是什么](#3.1 hostgroup 是什么)

[3.2 节点的自动归属:mysql_replication_hostgroups](#3.2 节点的自动归属:mysql_replication_hostgroups)

[3.3 节点的负载均衡](#3.3 节点的负载均衡)

[第四章 查询路由与读写分离规则](#第四章 查询路由与读写分离规则)

[4.1 路由规则的本质](#4.1 路由规则的本质)

[4.2 读写分离的经典规则](#4.2 读写分离的经典规则)

[mysql_query_rules 读写分离示例](#mysql_query_rules 读写分离示例)

[4.3 查询重写与缓存](#4.3 查询重写与缓存)

[第五章 健康检查与自动摘除](#第五章 健康检查与自动摘除)

[5.1 Monitor 线程的工作](#5.1 Monitor 线程的工作)

[5.2 故障自动摘除与恢复](#5.2 故障自动摘除与恢复)

[5.3 与 Orchestrator 的分工边界](#5.3 与 Orchestrator 的分工边界)

[第六章 配置三态分离:改不坏线上](#第六章 配置三态分离:改不坏线上)

[6.1 三层配置体系](#6.1 三层配置体系)

[6.2 标准操作流程:改、加载、保存](#6.2 标准操作流程:改、加载、保存)

配置变更标准流程

[第七章 用户管理与访问控制](#第七章 用户管理与访问控制)

[7.1 三类用户](#7.1 三类用户)

[7.2 应用用户的管理要点](#7.2 应用用户的管理要点)

读者收获与下一步

[8.1 读完本篇,你应该带走什么](#8.1 读完本篇,你应该带走什么)

[8.2 下一步建议](#8.2 下一步建议)

回顾与导读:从"大脑"到"闸门"

第二篇拆完了 Orchestrator------管理大脑的发现、存储、共识、切换四层机制。这一篇切换到另一半:ProxySQL。如果说 Orchestrator 是"决策者",ProxySQL 就是"执行者":所有应用 SQL 都从它这里过,它决定每一条 SQL 去哪台 MySQL,并在后端故障时自动把流量摘除或切换。

ProxySQL 的价值不能简单概括为"中间件"------它的连接池、路由、健康检查、配置热加载组合起来,直接决定了高可用方案里"切换对应用无感知"能否成立。读完这一篇,你将理解:读写分离为什么必须"规则先行"、连接池为什么能扛住连接风暴、配置为什么改不坏线上。

第一章 ProxySQL 整体架构与三大设计原则

1.1 架构概览

ProxySQL 是一个单进程、多线程的代理程序(基于 C++ 与 libev 事件驱动模型),对外暴露两个端口:

|------------|------------|---------------------------|
| 端口 | 用途 | 说明 |
| 6032 | Admin 管理接口 | DBA 连入执行配置与管理(类 MySQL 协议) |
| 6033 | MySQL 业务端口 | 应用连接入口,标准 MySQL 协议 |

进程内部按线程分工:Main 线程负责初始化与看护(watchdog 心跳检查,线程异常自动重启 ProxySQL)、Admin 线程监听 6032 处理配置、MySQL 线程池处理 6033 的业务查询、Monitor 线程负责后端健康检查。

1.2 三大设计原则

  • 最长运行时间(Max runtime):所有配置可在线修改、立即生效,无需重启进程------这是"配置三态分离"的动机。
  • 可扩展(Scalable):基于 libev 事件驱动模型,单线程可处理上千并发连接,水平扩展靠多实例 + 前端 LB。
  • 协议感知(Protocol-aware):深度理解 MySQL/PostgreSQL 协议,能解析 SQL、识别事务边界、追踪 prepared statement。

理解这三点,就理解了 ProxySQL 与普通 TCP 负载均衡的本质区别:它不是"转发字节",而是"看懂 SQL 再做决策"。

第二章 连接池:多路复用的魔法

2.1 为什么需要连接池

MySQL 每建立一个连接都要经历 TCP 握手、鉴权、会话初始化,高并发下连接数暴增会迅速耗尽 MySQL 的 max_connections,引发"连接风暴"雪崩。ProxySQL 在前端(应用↔ProxySQL)与后端(ProxySQL↔MySQL)之间做了一层解耦:

  • 前端连接:应用连 ProxySQL 的 6033,数量可以很大(取决于 ProxySQL 线程模型)。
  • 后端连接:ProxySQL 到 MySQL 的真实连接,由连接池统一管理、按需复用。

2.2 多路复用(Multiplexing)

ProxySQL 的核心魔法是连接多路复用:多个前端会话共享一个后端连接,SQL 按顺序复用同一 TCP 连接发送,响应再按会话分发回去。效果是:后端 MySQL 只需要维护远少于应用连接数的真实连接。

|-------------|------------------|------------------------|
| 对比项 | 直连 MySQL | 经 ProxySQL 连接池 |
| 应用连接数 | 与 MySQL 连接数 1:1 | 前端可远大于后端 |
| MySQL 压力 | 随应用实例数线性增长 | 后端连接数可控复用 |
| 连接风暴 | 无防护,易雪崩 | 池内复用,平滑吸收 |
| 会话状态 | 每连接独立 | 事务/临时表等特殊场景自动退避 |

需要特别说明:事务、锁、临时表、SESSION 级变量等有状态场景,ProxySQL 会自动"退避"为独占连接(不共享),保证语义正确------这是协议感知能力带来的智能行为。

第三章 hostgroup:读写分离的基石

3.1 hostgroup 是什么

hostgroup(主机组)是 ProxySQL 路由的基本单元:一组后端 MySQL 节点的集合。生产最典型的划分:

  • 写组(writer hostgroup,通常 id=10):主库,承接所有写 SQL 与强一致读。
  • 读组(reader hostgroup,通常 id=20):从库集合,承接普通读 SQL,组内负载均衡。

3.2 节点的自动归属:mysql_replication_hostgroups

手动维护"谁是主、谁是从"很累,ProxySQL 提供 mysql_replication_hostgroups 表:声明 writer_hostgroup 与 reader_hostgroup 后,Monitor 会自动根据各节点的 read_only 状态把节点归入对应组------主库 read_only=OFF 进写组,从库 read_only=ON 进读组。

这个机制与 Orchestrator 切换完美衔接:Orchestrator 把新主提升后(read_only 置 OFF、旧主置 ON),ProxySQL Monitor 探测到 read_only 变化,自动把流量切到新主------无需任何额外联动脚本,这是"半自动化联动"的底层原理。

3.3 节点的负载均衡

同一 hostgroup 内多个节点按 weight 权重轮询分发;健康检查失败(SHUTDOWN/OFFLINE_HARD)的节点被自动摘除,恢复后自动上线。

第四章 查询路由与读写分离规则

4.1 路由规则的本质

路由规则存储在 mysql_query_rules 表中,按 rule_id 从小到大逐条匹配,命中的第一条生效(可配置 continue 继续匹配)。规则匹配字段包括:SQL 文本(match_pattern)、SQL 指纹(match_digest)、用户名(username)、源地址(client_addr)等。

4.2 读写分离的经典规则

读写分离最少需要两条规则,且顺序至关重要------必须先匹配"特殊的读"(for update),再匹配"普通读":

mysql_query_rules 读写分离示例

-- 规则 1:SELECT ... FOR UPDATE 必须走主库(写组 10) INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (10, 1, '^SELECT.*FOR UPDATE', 10, 1); -- 规则 2:普通 SELECT 走从库(读组 20) INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (20, 1, '^SELECT ', 20, 1); -- 规则 3:兜底规则------其余所有 SQL 走主库(写组 10) INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (30, 1, '.*', 10, 1); -- 生效与持久化(三态流程) LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;

规则要点:for update 必须走主库(它要加写锁并读取最新数据);普通 select 走从库;兜底规则保证所有未匹配 SQL 落在主库,防止写 SQL 漏网。规则顺序错误(如把普通 select 规则放在 for update 之前)会导致 for update 被路由到只读从库而报错。

4.3 查询重写与缓存

  • 查询重写(query rewrite):在规则中配置 replace_pattern,把匹配的 SQL 替换后再转发------如读写分离中间层分表、兼容旧语法。
  • 查询缓存(query cache):对命中规则的查询结果做短时缓存(基于 SQL 指纹 + 参数),适合读多写少且一致性要求不高的场景;对一致性敏感的业务建议关闭。
  • SQL 指纹(digest):ProxySQL 对查询做参数归一化生成指纹,用于统计各类型 SQL 的执行次数与耗时,是慢查询分析与规则匹配的高效索引。

第五章 健康检查与自动摘除

5.1 Monitor 线程的工作

Monitor 线程周期性地对每个后端节点执行轻量探测(默认连接探测 + 可选只读状态探测),并把结果写入监控库:

  • 连接探测:能否成功建立连接(失败则标记 SHUNNED/离线)。
  • 只读状态探测:读取 read_only 值,用于 mysql_replication_hostgroups 的自动归属。
  • 复制延迟探测:读取从库复制延迟,超过 max_replication_lag 的从库自动从读组摘除。

5.2 故障自动摘除与恢复

后端节点连续探测失败后,ProxySQL 将其标记为离线(OFFLINE_HARD 或 SHUNNED),路由自动绕过;恢复健康后 Monitor 自动重新上线。整个过程无需人工介入、无需重启------这是"切换无感"的另一半保障。

5.3 与 Orchestrator 的分工边界

注意职责划分:ProxySQL 的摘除是"流量层面的即时保护"(秒级、无脑摘除);Orchestrator 的切换是"拓扑层面的根本恢复"(选出新主、重挂从库)。两者缺一不可:只有 ProxySQL 摘除而没有 Orchestrator 提升新主,写流量会全部失败;只有 Orchestrator 切换而没有 ProxySQL 感知,应用仍连旧主。

第六章 配置三态分离:改不坏线上

6.1 三层配置体系

|--------------|------------------------|--------------------------|
| 配置层 | 位置 | 说明 |
| RUNTIME(运行层) | 内存 | 当前实际生效的配置,改它才影响线上 |
| MEMORY(内存层) | 内存 | 可修改的工作区,LOAD 后进入 RUNTIME |
| DISK(持久层) | 磁盘 SQLite(proxysql.db) | SAVE 后重启不丢 |

6.2 标准操作流程:改、加载、保存

每次变更遵循"三步走":先在 MEMORY 中修改(INSERT/UPDATE),再 LOAD TO RUNTIME 生效,最后 SAVE TO DISK 持久化。

配置变更标准流程

-- 1. 在 MEMORY 层修改配置 INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (10, 'db-master', 3306); -- 2. 加载到 RUNTIME 生效 LOAD MYSQL SERVERS TO RUNTIME; -- 3. 保存到 DISK 持久化 SAVE MYSQL SERVERS TO DISK; -- 只改了 MEMORY 没 LOAD:线上无变化 -- 只 LOAD 没 SAVE:重启后配置丢失

常见坑:只 LOAD 不 SAVE,重启后配置回滚;只 SAVE 不 LOAD,线上没变化。三态分离的收益是"改了可以反悔"------LOAD 之前一切都在内存里,随时可以恢复,生产变更安全性大大提升。

第七章 用户管理与访问控制

7.1 三类用户

|--------------|--------------|---------------------------|
| 用户类型 | 连接端口 | 用途 |
| Admin 用户 | 6032 | DBA 配置管理(默认 admin/admin) |
| Monitor 用户 | 后端 | ProxySQL 探测 MySQL 健康状态 |
| 应用用户 | 6033 | 业务 SQL 入口(映射到后端 MySQL 账号) |

7.2 应用用户的管理要点

mysql_users 表管理应用用户:ProxySQL 用该用户名密码与后端 MySQL 建立连接(也支持将不同应用用户映射到不同后端账号),密码以哈希形式存储。修改后端 MySQL 密码时,需同步更新 mysql_users 并 LOAD/SAVE。

安全提示:默认 admin/admin 必须修改;Admin 端口(6032)建议仅监听内网或本机;应用用户遵循最小权限原则,与 MySQL 端授权保持一致。

读者收获与下一步

8.1 读完本篇,你应该带走什么

  • ProxySQL 三大设计原则:零重启改配置、libev 事件驱动可扩展、MySQL 协议感知。
  • 连接池多路复用:前端连接与后端连接解耦,一个后端连接服务多个前端会话,特殊场景自动退避独占。
  • hostgroup 是路由基石:写组 10 / 读组 20,mysql_replication_hostgroups 按 read_only 自动归类。
  • 读写分离规则顺序关键:for update 先于普通 select,兜底规则保证写 SQL 不漏网。
  • Monitor 健康检查:连接探测 + read_only 探测 + 延迟探测,故障自动摘除、恢复自动上线。
  • 配置三态分离(RUNTIME/MEMORY/DISK):改 → LOAD → SAVE 三步走,改不坏线上。

8.2 下一步建议

下一篇进入实战:从零搭建生产级 Orchestrator + ProxySQL 集群------主机规划、MySQL 前置配置、Orchestrator 部署、ProxySQL 配置、联动打通与故障演练,把前两篇的机制全部落地。

相关推荐
刘天远1 小时前
Agent系统接入编排:评分模型、状态机与Python门禁
数据库·人工智能·python
DBA_G2 小时前
GBase数据库安全“全牌照“技术解读:从等保四级到全密态计算的实践
数据库
码流子2 小时前
几万路监控怎么接:高速公路视频汇聚平台的架构设计与落地坑点
大数据·人工智能·物联网·算法·架构
我滴老baby2 小时前
工业物联网数据库选型:把计算能力放回第一维度
数据库·人工智能·架构·pdf
国际云,接待2 小时前
云服务器跨厂商迁移怎么尽量不停机:用 rsync、MySQL binlog 和 DNS TTL 做双阶段切换
运维·服务器·mysql
Doris__HE2 小时前
【元脑服务器NF8260G7-NF8260M7技术规格分享】
运维·服务器·网络·数据库·性能优化
用户7531057124513 小时前
五年前我吐槽 PG 的 32 位 XID 是狗皮膏药,今天它被治好了
数据库
DBA_G3 小时前
从湖仓一体到AI原生:GBase数据库的金融全栈技术实践
数据库
ChenLuck3 小时前
32 位 XID 的“狗皮膏药”被撕掉了:金仓 V9 的 64 位事务号实测与底层拆解
数据库