mysql主从复制可以做读写分离吗_mysql高可用实践说明

1次阅读

mysql主从复制本身不提供读写分离能力,需依赖应用层或中间件(如proxySQL、ShardingSphere)实现SQL路由;必须处理主从延迟、事务一致性、故障切换后配置同步等核心问题。

mysql主从复制可以做读写分离吗_mysql高可用实践说明

MySQL 主从复制本身不提供读写分离能力

主从复制只是把主库的写操作通过 binlog 同步到从库,它不参与 SQL 路由、连接分发或负载决策。读写分离需要额外组件在应用层或中间件层完成请求识别与转发。

常见错误现象:select 语句仍发到主库、从库延迟导致读到旧数据、事务内混用读写引发不一致。

  • 应用直连多实例时,必须自己判断 INSERT/UPDATE/delete 走主库,SELECT 走从库(需注意显式事务和 SELECT ... for UPDATE
  • ProxySQLMaxScale 时,要配置 mysql_query_rules 匹配 SELECT 并路由到 hostgroup 2(从库组),否则默认全走主库
  • spring Boot + AbstractRoutingDataSource 需重写 determineCurrentLookupKey(),且 @Transactional 方法内默认强制走主库,否则可能报错

从库延迟会直接破坏读写分离效果

主从延迟不是理论风险,而是常态。一旦 Seconds_Behind_Master > 0,应用从从库读取刚写入的数据就会失败——比如用户注册后立刻查个人页,返回 404。

使用场景中容易忽略:高并发写入、大事务、从库 IO 或 CPU 过载、网络抖动都会放大延迟。

  • 监控必须包含 SHOW SLAVE STATUSG 中的 Seconds_Behind_MasterExec_Master_Log_Pos 与主库 File/position 的差值
  • 关键业务读操作可加 SELECT /*+ MAX_EXECUTION_TIME(1000) */ ... 配合超时重试,或临时切回主库
  • 避免在从库执行 pt-online-schema-change 等长耗时操作,这类操作会阻塞 SQL 线程

GTID 模式下主从切换后读写分离更难维持

启用 gtid_mode=ON 后,主从关系可通过 GTID_SUBSET 自动定位位点,但读写分离中间件往往无法感知新主库身份,仍按旧拓扑转发请求。

典型问题:CHANGE MASTER TO ... GTID_SET 执行后,ProxySQL 的 mysql_servers 表未更新,导致 SELECT 继续发向已下线的旧从库。

  • 切换前必须调用 SAVE MYSQL SERVERS TO DISK 并确认 mysql_serversstatus 字段为 ONLINESHUNNED
  • ansible 或脚本触发 failover 时,需同步更新中间件配置 + 应用侧数据源地址(如 spring cloud Config 中的 spring.datasource.url
  • 不要依赖 read_only=ON 判断主从角色——故障切换后新主库可能仍残留该参数,造成写入被拒

真正可用的读写分离必须处理事务一致性边界

一个事务里既有写又有读,或者读操作依赖刚写的值(如生成订单号后立即查详情),此时强行把 SELECT 转给从库必然出错。

这是最容易被“自动读写分离”宣传误导的地方:没有中间件能 100% 正确解析 SQL 语义并保证事务上下文完整。

  • ShardingSphere-JDBC 的 master-slave 规则默认在事务内禁用从库路由,但若用 @Transactional(propagation = Propagation.NOT_SUPPORTED) 就会失效
  • MyCat 不支持跨库事务,遇到 XA START 会直接报错 Error 1105 (HY000): Unknown command
  • 最稳妥的做法是:对强一致性读,显式指定数据源(如 DataSourceType.MASTER),而非依赖自动识别

实际部署中,延迟监控、事务边界识别、failover 后配置同步这三点,比选型更消耗运维精力。

text=ZqhQzanResources