MyCAT读写分离需手动配置schema.xml中dataHost的writeHost(仅主库)与readHost(多个独立从库),balance="1"启用轮询但不自动剔除延迟高从库,强一致读须加注释/#mycat:db_type=master/或强制走主库。

MyCAT 对读写分离的“透明化”是假透明——应用层看似只连一个地址,但实际路由逻辑、主从延迟、事务一致性全得你亲手兜底。不配置好 schema.xml 和 rule.xml,不验证 show slave status 的延迟值,不绕过 MyCAT 直连从库测 SELECT,上线后大概率出现脏读或写失败。
怎么配 MyCAT 的 schema.xml 才让读写自动分流
核心不是写对标签,而是让 dataHost 真实绑定主从角色,且 writeHost 和 readHost 的 IP/端口/权重都指向真实实例:
-
writeHost必须只填主库地址(如192.168.12.161:3306),不能把从库混进去; -
readHost可以填多个,但每个都要独立声明(不是用逗号分隔),例如:<readHost host="slave1" url="192.168.12.162:3306" user="mycat" password="123456"/> <readHost host="slave2" url="192.168.12.163:3306" user="mycat" password="123456"/>
- 如果主库挂了,
writeHost下的readHost不会自动升主——MyCAT 默认不接管故障切换,得靠 MHA 或手动干预; -
balance="1"表示所有readHost轮询,但若某从库延迟高,请求照样打过去,不会自动剔除。
为什么 SELECT 还是打到主库?检查这三处
MyCAT 默认按 SQL 类型判断读写,但很多场景会“失效”:
- 显式事务里任何
SELECT都走主库(哪怕没写FOR UPDATE),因为 MyCAT 认为可能要更新; - 带
@@autocommit=0的连接,整个会话期间所有SELECT都路由到主库; - SQL 中含
SELECT ... FROM dual、SELECT VERSION()等系统查询,MyCAT 无法识别语义,直接发主库; - 如果
schema.xml里dataNode指向的是单节点(没配readHost),那所有读也必然落到主库。
主从延迟大时,MyCAT 怎么避免读到旧数据
MyCAT 本身不感知复制延迟,所谓“强一致性读”只能靠人工干预:
- 在 SQL 前加注释强制走主库:
/*#mycat:db_type=master*/ SELECT * FROM user WHERE id=123;; - 用
show slave status\G查Seconds_Behind_Master,超过阈值(比如 >5s)就临时切掉对应readHost; - 不要依赖
select @@server_id判断当前连接节点——MyCAT 会拦截并返回自己的 ID,得用SELECT @@hostname或直连 MySQL 查; - 业务关键读(如支付结果页)必须走主库,别信“延迟通常只有 200ms”这种话,大促时主从延迟飙到分钟级很常见。
最常被忽略的一点:MyCAT 启动后,schema.xml 修改必须重启服务才生效,热加载只支持部分 rule 变更;而 MySQL 主从状态变化(如从库宕机)MyCAT 不会自动重试连接,得靠 heartbeat 配置里的 mysql心跳检测 和日志轮询来发现——但这玩意儿默认 10 秒一次,故障窗口期不小。

















