我们期待已久的 MySQL 原生读写分离功能,现在终于在 8.2 版本中正式可用了!
过去,为了实现读扩展,我们需要手动将读流量分配到多个副本上,这通常需要在应用层进行繁琐的管理:指定写操作到某个节点,读操作到另一个节点。而在 MySQL 8.2 中, MySQL Router 现在可以自动识别 SQL 语句的读写属性,并将其智能地路由到正确的实例。对于写入操作,它会将其指向主实例(或异步复制架构中的源库);对于读取操作,则会将其导向只读的副本实例。
为了清晰地展示这一特性,本文将使用最简单的 MySQL 高可用架构 —— InnoDB ReplicaSet 进行演示。
MySQL InnoDB ReplicaSet 简介
InnoDB ReplicaSet 由一个源实例(Source,即主库)和一个(或多个)异步副本(Replica,即从库)构成,其架构示意图如下:

我们可以通过 MySQL Shell 查看该 ReplicaSet 的详细状态,输出如下:

启动并配置 MySQL Router 8.2
接下来,我们启动并配置 MySQL Router 8.2 来接入这个 ReplicaSet。Router 启动并完成引导配置后,会生成详细的连接信息:

从上图可以看出,Router 为 Classic 协议提供了一个特殊的端口 6450,标注为 Read/Write Split Connections,这正是实现读写分离的关键入口。同时,我们也可以在 MySQL Shell 中查询到已注册的 Router 信息:

查询结果显示,路由器版本为 8.2.0,并确认了其 rwSplitPort 端口为 6450。
体验智能读写分离
现在,我们使用 root 用户通过读写分离端口 6450 连接到 MySQL:

执行一个简单的 SELECT 查询,我们看到连接到了端口为 3320 的副本节点。接着,我们开启一个事务 (START TRANSACTION;),再次执行相同的 SELECT 查询,此时连接自动切换到了端口为 3310 的源节点。整个过程无需切换连接或更改端口,Router 根据 SQL 的上下文自动完成了路由。
我们还可以通过显式声明只读事务来观察这一行为:

当执行 START TRANSACTION READ ONLY; 开启一个只读事务后,随后的 SELECT 查询被路由到了 3320 副本节点。而在之前的写事务中,查询则被路由到 3310 源节点。事务回滚后,连接恢复默认状态。
配置解析与会话控制
在 MySQL Router 的配置文件(例如 mysqlrouter.conf)中,我们可以找到读写分离相关的配置段:
[routing:bootstrap_rw_split]
bind_address=0.0.0.0
bind_port=6450
destinations=metadata-cache://myreplica/?role=PRIMARY_AND_SECONDARY
routing_strategy=round-robin
protocol=classic
connection_sharing=1
client_ssl_mode=PREFERRED
server_ssl_mode=PREFERRED
access_mode=auto
关键参数 access_mode=auto 启用了自动的读写分离。此外,你还可以在会话级别使用 ROUTER SET 命令,强制指定当前会话的访问模式:

将 access_mode 设置为 read_write 后,查询指向了源节点(3310);设置为 read_only 后,查询则指向了副本节点(3320)。这为应用程序提供了更精细的控制能力。
总结
综上所述,MySQL Router 8.2 原生支持了开箱即用的读写分离功能。这是一项极具价值的能力,它允许我们在不修改任何应用程序代码的前提下,优化数据库的性能与扩展性。
通过此配置,所有的写入流量会自动定向到可读写的源实例,而读取流量则会负载均衡到只读的副本实例。这不仅提升了大规模 系统架构 下的数据处理能力和用户体验,也显著简化了数据库的运维管理与高可用部署。
对于希望深入探索数据库高级特性与最佳实践的开发者,可以持续关注 云栈社区 的相关技术讨论与分享。
原文来源:juejin.cn/post/7295304057656918026