mysql主从复制本身不提供负载均衡能力,需依赖proxysql等上层组件实现读写分离与负载均衡,且须结合延迟监控、健康检查及业务一致性策略综合配置。

MySQL主从复制本身不提供负载均衡能力
主从复制只是数据同步机制,不是负载分发系统。读请求可以发往从库,写请求必须走主库,但“把读请求自动分到多个从库”这件事,MySQL Server 层完全不参与——它没有内置的连接路由、健康检查或权重调度逻辑。
真正实现负载均衡,得靠上层组件。常见方案有三类:代理层(如 ProxySQL、MaxScale)、客户端驱动(如 mysql-connector-j 的 loadBalance 模式)、中间件+服务发现(如 ShardingSphere-Proxy 配合 Nacos)。选哪种,取决于你对透明性、运维复杂度和故障转移速度的要求。
ProxySQL 是目前最实用的读写分离+负载均衡方案
它轻量、热配置、支持 SQL 级别路由规则,并能自动剔除延迟过大或宕机的从库。部署时注意几个关键点:
-
mysql_servers表里必须给每个从库设置weight,否则默认为 1,无法体现真实负载差异 - 用
mysql_replication_hostgroups显式定义writer_hostgroup和reader_hostgroup,否则读写分离规则不会生效 -
monitor模块要开启,且mysql-monitor_username必须在所有后端 MySQL 实例上有REPLICATION CLIENT权限,否则延迟检测失效 - 不要依赖
max_replication_lag做唯一健康判断——它只查Seconds_Behind_Master,而这个值在 GTID + 多线程复制下可能长期为 0 却实际卡住;建议配合select 1连通性检测
Java 应用直连多从库时,mysql-connector-j 的 loadBalance 配置易踩坑
它靠客户端轮询分发连接,不感知数据库状态,也不做语句级读写判断。典型问题包括:
- URL 中必须显式启用:
jdbc:mysql:loadbalance://host1:3306,host2:3306,host3:3306/db?loadBalanceStrategy=roundrobin&loadBalanceEnableJMX=true,漏掉loadBalanceStrategy参数会导致 fallback 到单点 - 如果应用用了
setReadOnly(true),驱动才把连接发给从库;否则一律走第一个 host(即host1)——很多 ORM 框架默认不设只读,结果读流量全压在第一个从库上 - 从库挂了不会自动摘除,下次连接尝试仍会失败,需配合
loadBalanceAutoCommitStatementThreshold和重试逻辑 - 不支持按延迟动态调整权重,也无法识别事务中的读是否该强制走主库
负载均衡策略必须和业务一致性要求对齐
最常被忽略的是“刚写完立刻读”的场景。比如用户注册后跳转到个人页,此时从库可能还没同步到新记录。解决方案不是关掉负载均衡,而是分级处理:
- 对强一致性读(如订单详情、账户余额),直接走主库连接池,绕过负载均衡链路
- 对弱一致性读(如商品列表、评论数),走 ProxySQL 或客户端负载均衡
- 在应用层加
read-after-write路由标记(例如 ThreadLocal 里存一个 flag),让后续读请求临时命中主库,持续时间控制在秒级 - 避免在同一个事务里混用主从——MySQL 驱动不保证跨连接事务一致性,
XA又太重,基本不可行
延迟监控不能只看 Seconds_Behind_Master,得结合 pt-heartbeat 打点或 SHOW SLAVE STATUS 中的 Retrieved_Gtid_Set 与 Executed_Gtid_Set 差值来判断真实滞后。这点一旦疏忽,负载均衡反而会把流量导给“假活”的从库。











