MySQL 读写分离:用 ProxySQL 实现 “读走从库,写走主库”(附延迟问题解决方案)
前阵子帮某电商平台优化性能,他们的主库 QPS 长期维持在 8000+,其中 70% 是查询操作(查订单、商品详情),导致主库 CPU 使用率经常飙到 90% 以上,偶尔还会因为锁等待超时丢单。后来用 ProxySQL 做了读写分离,把读请求全部分流到 3 个从库,主库 QPS 直接降到 2400,CPU 使用率稳定在 30%,再也没出现过超时问题。
读写分离是 MySQL 性能优化的 “分水岭” 方案 —— 当单库读写压力过大时,通过 “主库写、从库读” 的方式分散负载,能让系统支撑的并发量提升 3-5 倍。但很多人只知道 “读走从库”,却不懂 “怎么判断 SQL 该走主库还是从库”“从库延迟了怎么办”“中间件怎么选”,结果要么分离不彻底,要么读从库时拿到旧数据。
这篇是 MySQL 专栏的性能分流实战篇,核心目标是帮你从 “知道读写分离” 进阶到 “能在生产环境落地 ProxySQL 方案”。全文用电商订单系统的真实场景贯穿,包含 “ProxySQL 搭建全步骤”“读写规则配置”“从库延迟从 3 秒降到 0.1 秒的优化”,每步都附可复现的命令和验证方法,新手跟着做也能快速上手。
一、先搞懂:为什么要做读写分离?(用 “超市收银” 类比)
单库 MySQL 就像 “超市只有一个收银台”—— 不管是买东西(写操作,如下单)还是查价格(读操作,如查库存),都得排队。当人多了(并发高了),收银台就会堵死。
读写分离就像 “超市分设‘买单通道’和‘咨询台’”:
- 买单通道(主库):只处理 “付钱”(写操作:INSERT/UPDATE/DELETE),专注高效;
- 咨询台(从库):处理 “查价格、问库存”(读操作:SELECT),多个咨询台分流压力。
1. 读写分离能解决的 3 个核心问题
- 主库读压力过大:电商大促时,“查商品详情” 的请求是 “下单” 的 10 倍以上,全走主库会导致主库响应变慢;
- 主库连接数不足:MySQL 默认最大连接数 151,大量读请求占满连接,写请求会因 “连接超时” 失败;
- 异地访问延迟:北京主库,广州用户查数据,直接访问主库延迟 50ms,访问广州从库延迟 10ms。
2. 3 种常见读写分离方案对比(企业级选型指南)
| 方案类型 | 实现方式 | 优点 | 缺点 | 适用场景 | 
|---|---|---|---|---|
| 应用层分离 | 代码中判断 SQL 类型,写连主库,读连从库 | 简单直接,无需额外组件 | 代码侵入性强,新增从库需改代码 | 小型项目,开发资源紧张 | 
| 中间件分离 | 用 ProxySQL/MyCat 做中间层,自动路由 | 无代码侵入,支持动态扩缩容 | 需维护中间件,有一定学习成本 | 中大型项目,核心业务 | 
| 驱动层分离 | 用 MySQL Connector/J 的读写分离功能 | 轻量,对应用透明 | 规则配置灵活度低,不支持复杂路由 | Java 项目,简单读写分离需求 | 
企业级结论:90% 的中大型项目会选ProxySQL—— 它是 MySQL 官方推荐的中间件,支持自动识别读写 SQL、故障检测、从库权重分配,稳定性经过阿里、腾讯等大厂验证。
二、ProxySQL 核心原理:它是怎么 “分辨” 读写请求的?
ProxySQL 就像 “超市入口的引导员”,会先看你是 “要买单” 还是 “要咨询”,再引导到对应通道。它的核心工作流程分 3 步:
1. 连接池管理:复用连接,减少开销
- 应用不直接连数据库,而是连 ProxySQL 的 3306 端口;
- ProxySQL 会和后端主从库建立 “长连接” 并维护连接池,应用请求来时直接复用连接(避免频繁创建连接的开销);
- 比如应用需要 1000 个连接,ProxySQL 只需和主库保持 200 个长连接,大幅减少数据库的连接压力。
2. 查询路由:判断 SQL 该走主库还是从库
ProxySQL 通过 “规则匹配” 决定 SQL 的走向,核心规则如下:
- 写操作强制走主库:只要 SQL 包含INSERT/UPDATE/DELETE/ALTER,或SELECT ... FOR UPDATE(加锁读),直接路由到主库;
- 读操作优先走从库:普通SELECT语句,按从库权重分配到不同从库;
- 特殊表强制走主库:比如 “秒杀库存表”,即使是SELECT也必须读主库(避免从库延迟导致超卖)。
3. 健康检查:自动剔除故障节点
- ProxySQL 会定期(默认每 200ms)给主从库发 “心跳检测”(如SELECT 1);
- 若从库连续 3 次无响应,自动将其从可
