ProxySQL 全景解读
定义
ProxySQL 是 MySQL 协议级的高性能中间代理,位于应用与 MySQL 实例之间,对 SQL 流量做透明路由、负载均衡、缓存、限流、审计、故障转移 等操作。
1. 诞生背景
- 传统痛点:
- 主从读写分离需要在业务里维护多套连接串。
- 单实例故障导致连接雪崩。
- DBA 想灰度上线、在线切换、SQL 审计,但业务代码改不动。
- 早期方案:MySQL Proxy(已停滞)、Atlas、Cobar 等,功能或性能总差一点。
- 2015 年:ProxySQL 以 C++11 重写,主打 “零侵入、热加载、高并发”。
2. 核心功能
| 功能 |
一句话解释 |
典型场景 |
| 读写分离 |
按正则/Schema/注释路由到不同 hostgroup |
主写从读 |
| 负载均衡 |
权重、最少连接、响应时间、复制延迟感知 |
多从库分摊读 |
| 连接池 |
与后端维持少量长连接,前端可并发上万 |
高并发短连接 |
| 查询缓存 |
TTL + 哈希缓存,自动失效 |
报表、字典表 |
| 故障探测 |
心跳、复制延迟、GTID、只读状态 |
故障自动剔出 |
| 在线重载 |
修改配置无需重启,毫秒级生效 |
灰度变更 |
| 审计 & 限流 |
正则匹配、用户级、SQL 级黑名单 |
防慢查询打爆 |
| 防火墙 |
基于规则集的 SQL 注入防御 |
安全合规 |
3. 架构速览
┌────────────┐ ┌─────────────┐ ┌────────────┐
│ App │────▶│ ProxySQL │────▶│ MySQL (R/W)│
└────────────┘ │ (6033) │ └────────────┘
│ Admin │
│ (6032) │
└─────────────┘
- 6033 业务端口,兼容 MySQL 协议,客户端无感知。
- 6032 管理端口,SQL 接口,支持
SELECT/UPDATE/INSERT 改配置。
- 多层表
mysql_servers 后端列表
mysql_users 账号映射
mysql_query_rules 路由规则
runtime_* 实时生效,disk 层持久化,config file 仅启动加载。
4. 优势总结
- 性能
- 单核可达 50w QPS(官方基准)。
- epoll + 多线程,CPU 亲和,零拷贝转发。
- 零侵入
- 热加载
- 规则修改
LOAD ... TO RUNTIME; SAVE ... TO DISK; 毫秒级生效。
- 细粒度路由
- 支持正则、Schema、用户、事务状态、注释、prepare 语句。
- 高可用
- 支持 ProxySQL Cluster(v2.0+),多实例配置同步。
- 生态
- Prometheus exporter、Orchestrator、Percona Toolkit 等工具链完善。
- 与 K8s Operator(如 prpxysql-operator)深度集成。
5. 劣势 & 挑战
| 维度 |
问题 |
缓解方案 |
| 学习曲线 |
20+ 张系统表,新手易迷路 |
官方文档 + 官方镜像沙箱 |
| 单点故障 |
早期无集群 |
2.x 原生 Cluster + VIP/Keepalived |
| 资源消耗 |
高并发 CPU 占满 |
多实例 + NUMA 绑定 |
| 延迟 |
多一跳,平均 +0.2 ms |
同机房部署、开启 fast_forward |
| 复杂查询 |
大事务、prepare 语句规则难写 |
渐进式灰度、先跑监控 |
| 版本升级 |
1.x → 2.x 有表结构变化 |
官方升级脚本 + 双实例并行 |
6. 与同类方案对比
| 特性 |
ProxySQL |
MySQL Router |
MaxScale |
Atlas |
| 协议层 |
MySQL |
MySQL |
MySQL + Binlog |
MySQL |
| 读写分离 |
✅ 正则/规则 |
✅ 基础 |
✅ 高级 |
✅ 基础 |
| 连接池 |
✅ 内核 |
❌ |
✅ |
✅ |
| 查询缓存 |
✅ TTL |
❌ |
✅ |
❌ |
| 审计/限流 |
✅ SQL 级 |
❌ |
✅ |
❌ |
| 开源协议 |
GPL-3.0 |
GPL-2.0 |
BSL 1.1 |
GPL-2.0 |
| 性能 |
高 |
中 |
高 |
中 |
7. 典型落地场景
| 场景 |
架构要点 |
| K8s 微服务 |
每个 Namespace 部署一组 ProxySQL StatefulSet,Service 暴露 6033,ConfigMap 注入规则。 |
| SaaS 多租户 |
按租户维度建 hostgroup,mysql_query_rules 里根据 schemaname 路由到不同实例。 |
| 金融级高可用 |
两机房三实例集群 + Orchestrator 自动主从切换 + ProxySQL 故障探测,RTO < 30s。 |
| 实时报表 |
报表 SQL 命中 query_cache,缓存 60s,QPS 提升 5 倍,后端 CPU 下降 70%。 |
8. 总结
ProxySQL 是一把 “瑞士军刀”,把 DBA 的日常痛点(读写分离、故障转移、SQL 审计)都做成 可热插拔的规则表,让 开发和运维第一次有了共同语言。
当你犹豫要不要在代码里写多个数据源时,先想想:
“能不能交给 ProxySQL 一行配置解决?”
延伸阅读
常用命令
下面是 “常用 ProxySQL 管理命令速查表”,全部基于 6032 管理端口 的 SQL 语法。
1. 连上管理接口
mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt='ProxySQL> '
2. 后端 MySQL 实例
| 目的 |
命令 |
| 查看所有节点 |
SELECT hostgroup_id,hostname,port,status,weight FROM mysql_servers; |
| 临时上线 / 下线 |
UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostname='10.0.0.2'; |
| 永久新增节点 |
INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (10,'10.0.0.5',3306); |
| 立即生效 |
LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK; |
3. 用户与权限
| 目的 |
命令 |
| 查看用户 |
SELECT username,password,default_hostgroup FROM mysql_users; |
| 新增业务用户 |
INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('app','app_pwd',10); |
| 立即生效 |
LOAD MYSQL USERS TO RUNTIME; SAVE MYSQL USERS TO DISK; |
4. 路由规则
| 目的 |
命令 |
| 查看规则 |
SELECT rule_id,match_pattern,destination_hostgroup,apply FROM mysql_query_rules ORDER BY rule_id; |
| 按正则路由 |
INSERT INTO mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) VALUES (100,1,'^SELECT.*FOR UPDATE',10,1); |
| 按注释路由 |
INSERT INTO mysql_query_rules(active,match_pattern,destination_hostgroup) VALUES (1,'/\*master\*/',10); |
| 立即生效 |
LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK; |
5. 连接池 & 变量
| 目的 |
命令 |
| 查看全局变量 |
SELECT * FROM global_variables WHERE variable_name LIKE '%threads%'; |
| 动态修改变量 |
SET mysql-max_connections=3000; |
| 立即生效 |
LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK; |
6. 监控 & 健康检查
| 目的 |
命令 |
| 查看心跳日志 |
SELECT hostname,ping_error,ping_time FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 10; |
| 查看复制延迟 |
SELECT hostname,repl_lag FROM monitor.mysql_server_replication_lag_log ORDER BY time_start_us DESC LIMIT 10; |
| 立即重试 |
UPDATE mysql_servers SET status='ONLINE' WHERE hostname='10.0.0.3'; |
7. 统计 & 性能
| 目的 |
命令 |
| 实时 QPS |
SELECT SUM(Queries) AS total_qps FROM stats_mysql_global; |
| Top 慢查询 |
SELECT hostgroup,username,digest_text,sum_time,count_star FROM stats_mysql_query_digest ORDER BY sum_time DESC LIMIT 10; |
| 连接池使用率 |
SELECT hostgroup,srv_host,ConnUsed,ConnFree,ConnOK FROM stats_mysql_connection_pool; |
8. 缓存
| 目的 |
命令 |
| 查看缓存条目 |
SELECT count(*) FROM stats_mysql_query_cache; |
| 清空缓存 |
SELECT * FROM stats_mysql_query_cache_reset; |
9. 集群(v2.x)
| 目的 |
命令 |
| 查看集群节点 |
SELECT hostname,checksum,epoch FROM runtime_proxysql_servers; |
| 手动同步配置 |
LOAD ... FROM DISK; LOAD ... TO RUNTIME; (所有节点执行) |
10. 一键“三板斧”
在任何一台 ProxySQL 节点上执行,即可把 内存 → 运行 → 磁盘 全部保存:
SAVE MYSQL VARIABLES TO DISK;
SAVE MYSQL USERS TO DISK;
SAVE MYSQL SERVERS TO DISK;
SAVE MYSQL QUERY RULES TO DISK;
SAVE ADMIN VARIABLES TO DISK;
11. 最常用 10 条速记
| 场景 |
一句话命令 |
| 连管理 |
mysql -uadmin -padmin -P6032 |
| 看后端 |
SELECT * FROM mysql_servers; |
| 看用户 |
SELECT * FROM mysql_users; |
| 看路由 |
SELECT * FROM mysql_query_rules; |
| 看变量 |
SHOW VARIABLES LIKE '%threads%'; |
| 看 QPS |
SHOW MYSQL STATUS LIKE 'Questions'; |
| 看 Top SQL |
SELECT * FROM stats_mysql_query_digest ORDER BY sum_time DESC LIMIT 5; |
| 下线节点 |
UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostname='x'; LOAD MYSQL SERVERS TO RUNTIME; |
| 加用户 |
INSERT INTO mysql_users(...) VALUES (...); LOAD MYSQL USERS TO RUNTIME; |
| 加规则 |
INSERT INTO mysql_query_rules(...) VALUES (...); LOAD MYSQL QUERY RULES TO RUNTIME; |
把这张表贴到 ~/.my.cnf 旁,效率立刻 +200%。
如需图形化,可对接 ProxySQL Admin Web UI 或 Percona PMM。