连接池、读写分离与查询路由机制
- 三大设计原则:零重启改配置、事件驱动、协议感知
- 连接池多路复用:一个后端连接服务多个前端会话
- 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 配置、联动打通与故障演练,把前两篇的机制全部落地。