mysql router 8.2+ 在 innodb cluster 或 replicaset 场景下可自动识别读写语句并动态路由,老版本仅按角色静态转发连接,不解析 sql;必须正确配置 metadata_cache、routing:read_write 和 routing:read_only 三节,且应用需主动连接对应端口或依赖 8.2+ 的 auto access_mode 才能实现读写分离。

MySQL Router 本身不解析 SQL,不能自动区分 SELECT 和 INSERT 并做路由——读写分离必须靠应用主动连不同端口,或依赖 MySQL 8.2+ 的新行为(仅限 InnoDB Cluster / ReplicaSet 场景)。别指望配完就自动分流。
MySQL Router 能不能自动识别读写语句?
不能,除非你用的是 MySQL 8.2+ 且后端是 InnoDB Cluster 或 ReplicaSet。老版本(8.1 及之前)完全不看 SQL 内容,只按配置把连接转发到指定角色节点。
- 8.2 之前:必须让应用自己决定连
6446(写)还是6447(读),Router 不干预 SQL - 8.2 开始:在
ReplicaSet模式下,Router 会根据语句类型 + 事务状态动态路由——SELECT默认走从库,但开启事务后自动切回主库;仍需启用--use-gr或正确 bootstrap - 普通主从复制(非 Group Replication)环境,哪怕 8.2 也**不支持**语句级识别,只能手动配
destinations=192.168.1.10:3306,192.168.1.11:3306这种静态列表
配置文件里最关键的三个 section 怎么写?
漏掉任一节,Router 启动失败或路由失效。名字必须完全一致,大小写敏感,顺序无关。
-
[metadata_cache:mycluster]:必须存在,且bootstrap_server_addresses至少填一个在线的集群节点地址,如mysql://10.0.1.10:3306;ttl=5推荐,太大会延迟故障感知 -
[routing:read_write]:绑定端口(如6446),destinations=metadata-cache://mycluster/default?role=PRIMARY——注意mycluster必须和 metadata_cache 节名字一致 -
[routing:read_only]:绑定另一端口(如6447),destinations=metadata-cache://mycluster/default?role=SECONDARY;若用静态地址,写成destinations=10.0.1.11:3306,10.0.1.12:3306即可,不用 metadata-cache
启动前必须确认的三件事
Router 启动报错“Failed to fetch cluster metadata”或连不上,90% 出在这三处。
- MySQL 实例是否已启用
group_replication或已加入InnoDB Cluster?单主从环境要手动补mysql_innodb_cluster_metadata库里的角色信息,否则 metadata-cache 拉不到数据 - Router 所在机器能否直连所有 MySQL 实例的
3306(SQL 端口)和33061(Group Replication 心跳端口)?防火墙常封掉33061,导致元数据同步失败 - 配置中指定的用户(如
GreatSQL@172.16.16.10)是否有SELECT权限访问performance_schema.replication_group_members和mysql_innodb_cluster_metadata?缺权限时 Router 默认 fallback 到全走 PRIMARY
应用怎么用才不踩坑?
不是配完 Router 就万事大吉。应用层的连接逻辑直接决定是否真能读写分离。
- 写操作必须连
localhost:6446(或你配的read_write端口),读操作必须连localhost:6447(read_only端口)——Router 不会重定向已建立的连接 - 如果应用用了连接池(如 HikariCP),确保池配置里
jdbcUrl明确指向对应端口,别复用同一个 URL - 事务中混用读写:8.2+ 在
ReplicaSet下能自动处理,但普通主从环境必须全程走6446,否则从库查不到刚写的行 - 从库延迟高?Router 不感知复制延迟,也不会自动剔除慢从库——得靠 Cluster 自身故障转移,或换 ProxySQL 做基于
mysql_replication_hostgroups的延迟感知路由
真正麻烦的不是配 Router,而是验证它到底有没有按预期工作:连上 6447 后执行 SELECT @@server_id,结果是不是从库 ID;写入后立刻用同一连接读,会不会报错或读不到——这些才是容易被忽略的验证点。











