PolarDB MySQL集群自带读写分离功能。应用程序只需连接一个集群地址,写请求会自动发往主节点,读请求会自动根据各节点的负载(当前未完成的请求数)发往主节点或只读节点。
功能优势
- 读一致性
在PolarDB的链路中间层进行读写分离时,中间层会追踪各个节点已经应用的Redo日志位点,即日志序号(Log Sequence Number,简称LSN),同时每次数据更新时,PolarDB会记录此次更新的位点为Session LSN。当有新请求到来时,PolarDB会比较Session LSN和当前各个节点的LSN,仅将请求发往LSN大于或等于Session LSN的节点,从而保证了会话一致性。表面上看该方案可能导致主节点压力大,但是因为PolarDB是物理复制,速度极快。在上述场景中,当更新完成后,返回客户端结果时复制就同步在进行,而当下一个读请求到来时,主节点和只读节点之间的数据复制极有可能已经完成。且大多数应用场景都是读多写少,所以经验证在该机制下既保证了会话一致性,也保证了读写分离负载均衡的效果。
- 原生支持读写分离,提升性能
如果您在云上通过自己搭建代理层实现读写分离,在数据到达数据库之前需要经历多个组件的语句解析和转发,对响应延迟有较大的影响。而PolarDB读写分离在已有的高安全链路中直接内置,没有任何额外的组件来消耗时间,能够有效降低延迟,提升处理速度。
- 维护方便
在传统模式下,您需要在应用程序中配置主节点和每个只读节点的连接地址,并且对业务逻辑进行拆分,才能实现将写请求发往主节点而将读请求发往各个节点。
PolarDB提供集群地址,应用程序连接该地址后即可对主节点和只读节点进行读写操作,读写请求会被自动转发,转发逻辑完全对使用者透明,可降低维护成本。
同时,您只需添加只读节点的个数,即可不断扩展系统的处理能力,应用程序无需做任何修改。
- 节点健康检查,提升数据库系统的可用性
读写分离模块自动对集群内的所有节点进行健康检查,当发现某个节点宕机或者延迟超过阈值后,将不再分配读请求给该节点,读写请求在剩余的健康节点间进行分配。以此确保单个只读节点发生故障时,不会影响应用的正常访问。当节点被修复后,PolarDB会自动将该节点纳回请求分配体系内。
- 免费使用,降低资源及维护成本
免费提供读写分离功能,无需支付任何额外费用。
转发逻辑
- 可读可写模式转发逻辑如下:
- 只发往主节点:
- 所有DML操作(INSERT、UPDATE、DELETE、SELECT FOR UPDATE)。
- 所有DDL操作(建表/库、删表/库、变更表结构、权限等)。
- 所有事务中的请求。
- 用户自定义函数。
- 存储过程。
- EXECUTE语句。
- Multi Statements。
- 使用到临时表的请求。
- SELECT last_insert_id()。
- 所有对用户变量的查询和更改。
- SHOW PROCESSLIST。
- KILL(SQL语句中的KILL,非命令KILL)。
- 发往只读节点或主节点:
- 非事务中的读请求。
- COM_STMT_EXECUTE命令。
- 总是发往所有节点:
- 所有系统变量的更改。
- USE命令。
- COM_STMT_PREPARE命令。
- COM_CHANGE_USER/COM_QUIT/COM_SET_OPTION等命令。
- 只发往主节点:
- 只读模式转发逻辑如下:
- 不允许执行DDL、DML操作。
- 所有请求按照负载均衡的方式转发到各只读节点。
- 所有请求不会转发到可读可写节点。
使用限制
- 若执行了Multi Statements或存储过程,当前连接的后续请求会全部路由到主节点,需断开当前连接并重新连接才能恢复读写分离。
- 请勿在运行Multi Statements或调用存储过程时修改环境变量,例如
set names utf8mb4;select * from t1;
。如果在运行Multi Statements或存储过程中修改了环境变量,将会导致请求路由到只读库和主库查到的数据可能不一致。 - 集群地址在只读模式下,不支持设置环境变量,例如
set @endtime=now(); select * from tab where dt < @endtime
。如果集群地址在只读模式下设置了环境变量,可能会导致查询无法获得正确的环境变量。 - 使用视图时无法保证会话一致性,例如
CREATE VIEW tab2 AS SELECT * FROM tab1; INSERT INTO tab1(key, value) (1, 1); SELECT * FROM tab2 where key=1;
。如果使用了视图,可能会因为延迟而查不到结果。 - 暂时不支持
show full processlist;
。
功能特性
PolarDB的读写分离功能主要包含以下特性。
- 负载均衡
PolarDB支持基于负载的自动调度策略,读请求将在多个只读节点中按照活跃连接数自动调度,来保证多个只读节点间的负载均衡。
- 一致性级别
由于PolarDB使用异步复制的方式进行主从同步,该模式在读写分离模式下,可能出现一个写请求之后的读请求无法获得最新的写结果,导致不一致。PolarDB提供了最终一致性、会话读一致性以及全局一致性级别供您选择,详情请参见一致性级别。
- 事务拆分
在默认的Read Commited隔离级别下,当数据库接收到开启事务的语句(例如
begin
或set autocommit=0
)时,不会立即开启事务,而是在发生写操作时才正式开启事务。通常情况数据库代理会将事务内的所有请求都发送到主节点,但由于某些框架实现的原因会将所有请求封装到事务中,导致主节点负载过大。此时您可以开启事务拆分功能,开启后数据库代理会识别当前事务的真正状态,将正式开启事务前的读请求通过负载均衡模块分流至只读节点。
说明- 读写分离模式下,事务拆分功能默认开启,如何修改事务拆分状态请参见修改集群地址。
- 某些业务对一致性有较高要求,开启事务拆分后将不满足一致性,因此在事务拆分前请充分评估事务拆分功能是否适用于您的业务。
- 更改事务拆分设置后,仅对新建连接生效。
- 主库不接受读
当主库配置为不接受读时,普通的读请求将不再路由到主库。而事务内,一致性要求的读还是会被路由到主库,以保证业务的需求,另外当所有只读节点出现故障后读请求也会路由到主库。如果业务对一致性的要求较低,可以通过设置一致性级别为最终一致性来减少读请求到主库,也可以通过事务拆分功能来减少真正事务前的读请求路由到主库。 广播的请求(例如SET或PREPARE)还是会被路由到主库上。
说明- 读写分离模式下,主库不接受读默认开启。如何修改主库不接受读状态请参见修改集群地址。
- 更改主库不接受读后立即生效。
- Hint语法
PolarDB支持如下Hint语法:
说明- 若您需要通过MySQL官方命令行执行上述Hint语句,请在命令行中加上-c参数,否则该Hint会被MySQL官方命令行过滤导致Hint失效,具体请参见MySQL官方命令行。
- Hint的路由优化级别最高,不受一致性级别和事务拆分的约束,使用前请进行评估。
- Hint语句里不要有改变环境变量的语句,例如
/*FORCE_SLAVE*/ set names utf8;
等,这类语句可能导致后续的业务出错。
- 支持在SQL语句前加上
/*FORCE_MASTER*/
或/*FORCE_SLAVE*/
强制指定这条SQL的路由方向。例如
select * from test
默认会路由到只读节点,改为/*FORCE_MASTER*/ select * from test
就会路由到主节点。 - 支持在SQL语句前加上
/*force_node='<节点ID>'*/
强制指定在某节点执行某查询命令。例如
/*force_node='pi-bpxxxxxxxx'*/ show processlist
,该show processlist
命令只在pi-bpxxxxxxxx
节点执行。如果该节点发生故障,则返回报错force hint server node is not found, please check.
。 - 支持在SQL语句前加上
/*force_proxy_internal*/set force_node = '<节点ID>'
强制指定在某节点执行所有查询命令。例如
/*force_proxy_internal*/set force_node = 'pi-bpxxxxxxxx'
,执行该命令后,后续所有查询命令只发往pi-bpxxxxxxxx
节点,如果该节点发生故障,则返回报错set force node 'rr-bpxxxxx' is not found, please check.
。说明 通常不建议使用/*force_proxy_internal*/
语法,会导致后续所有查询请求都发往该节点,读写分离失效。
在文档使用中是否遇到以下问题
更多建议
匿名提交