主从复制仅实现数据同步,不自动路由请求;读写分离需应用或中间件主动将SELECT发往从库、DML发往主库,否则所有请求默认落在主库。

主从复制本身不提供读写分离能力,它只是数据同步机制;读写分离必须由上层(应用或中间件)主动路由请求才能生效。
为什么 SHOW SLAVE STATUS 显示正常,但业务还是全打到主库?
这是最常被误解的点:MySQL 主从复制只负责把 binlog 从主库传到从库并重放,它不会拦截、改写或分发任何客户端发来的 SQL 请求。所有连接默认连的都是你代码里写的地址 —— 如果你没改,那 SELECT 和 INSERT 全都落在主库上,从库完全“躺平”。
- 检查应用连接字符串是否硬编码了主库 IP 或域名
- 确认 ORM 框架(如 MyBatis、Hibernate)没有开启读写分离插件或配置
- 如果用了连接池(如 HikariCP),注意其不自带读写分离逻辑,需配合
AbstractRoutingDataSource等手动实现
基于应用层做读写分离要注意哪些关键点?
这类方案侵入性强但可控性高,适合已有稳定架构、对延迟敏感的场景。
- 区分读/写操作不能只看 SQL 关键字 ——
SELECT ... FOR UPDATE是写操作,必须走主库 - 事务内所有语句(包括
SELECT)必须路由到同一节点,否则会读到过期数据或报错 - 避免在事务中跨库查询,比如主库查用户、从库查订单,这种设计会破坏一致性边界
- 建议用注解或线程上下文标记读偏好(如
@ReadOnly),而非依赖 SQL 解析,后者易误判且性能差
用 MyCAT 做代理时,dataHost 和 writeHost/readHost 怎么配才不出错?
MyCAT 的核心是逻辑库映射到物理节点,配置错一个字母就可能导致写请求发到从库、或读请求卡死。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
writeHost必须指向主库,且该节点的host、port、user要和主库实际一致;readHost必须指向已启动复制且SHOW SLAVE STATUS\G中Slave_IO_Running和Slave_SQL_Running都为Yes的从库 - 同一个
dataHost下,writeHost只能有一个,readHost可多个,但 MyCAT 默认轮询,不保证负载均衡或延迟感知 - 务必关闭从库的
super_read_only=ON(不是read_only),否则 MyCAT 发送的健康检测语句(如SELECT USER())会失败,导致节点被下线 - 测试阶段用
explain sql查看 MyCAT 路由结果,确认SELECT真的进了readHost
主从延迟大时,读请求直接打到从库会有什么后果?
这是最容易被忽略的线上事故源头:主从异步复制天然存在延迟,高峰期可能达秒级甚至分钟级。
- 用户刚注册完立刻查个人资料,返回空 —— 因为
INSERT已提交,但从库还没同步完 - 订单支付成功后跳转订单页,显示“未支付” —— 主库已更新状态,从库 relay log 还卡在前一条
- 解决方案不是禁用从库读,而是分级处理:强一致性读(如订单详情、账户余额)强制走主库;弱一致性读(如商品评论、历史浏览)可走从库
- MyCAT 支持
/*#mycat:db_type=master*/这类 hint 强制走主库,比改代码更轻量
真正难的不是配置主从或搭 MyCAT,而是厘清哪些读可以接受延迟、哪些必须强一致,以及如何让这套逻辑在业务演进中不散架。数据库没感情,但业务有状态 —— 所有读写分离方案,最终都要回到“这个请求此刻该看到什么数据”这个问题上来。










