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

来源:这里教程网 时间:2026-02-28 20:45:56 作者:

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

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

常见错误现象:

SELECT
语句仍发到主库、从库延迟导致读到旧数据、事务内混用读写引发不一致。

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

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

主从延迟不是理论风险,而是常态。一旦

Seconds_Behind_Master
> 0,应用从从库读取刚写入的数据就会失败——比如用户注册后立刻查个人页,返回 404。

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

监控必须包含
SHOW SLAVE STATUS\G
中的
Seconds_Behind_Master
Exec_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_servers
status
字段为
ONLINE
SHUNNED
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 后配置同步这三点,比选型更消耗运维精力。

相关推荐