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提供了最终一致性、会话读一致性以及全局一致性级别供您选择,详情请参见PolarDB一致性级别

  • 事务拆分

    在默认的Read Commited隔离级别下,当数据库接收到开启事务的语句(例如beginset autocommit=0)时,不会立即开启事务,而是在发生写操作时才正式开启事务。

    通常情况数据库代理会将事务内的所有请求都发送到主节点,但由于某些框架实现的原因会将所有请求封装到事务中,导致主节点负载过大。此时您可以开启事务拆分功能,开启后数据库代理会识别当前事务的真正状态,将正式开启事务前的读请求通过负载均衡模块分流至只读节点。

    事务拆分
    说明
    • 读写分离模式下,事务拆分功能默认开启,如何修改事务拆分状态请参见修改集群地址
    • 某些业务对一致有较高要求,开启事务拆分后将不满足一致,因此在事务拆分前请充分评估事务拆分功能是否适用于您的业务。
    • 更改事务拆分设置后,仅对新建连接生效。
  • 主库不接受读

    当主库配置为不接受读时,普通的读请求将不再路由到主库。而事务内,一致性要求的读还是会被路由到主库,以保证业务的需求,另外当所有只读节点出现故障后读请求也会路由到主库。如果业务对一致的要求较低,可以通过设置一致性级别为最终一致性来减少读请求到主库,也可以通过事务拆分功能来减少真正事务前的读请求路由到主库。 广播的请求(例如SET或PREPARE)还是会被路由到主库上。

    说明
    • 读写分离模式下,主库不接受读默认开启。如何修改主库不接受读状态请参见修改集群地址
    • 更改主库不接受读后立即生效。
  • HINT语法

    您可以在SQL语句前加上/*FORCE_MASTER*//*FORCE_SLAVE*/强制指定这条SQL的路由方向。

    例如select * from test默认会路由到只读节点,改为/*FORCE_MASTER*/ select * from test就会路由到主节点。

    说明
    • 若您需要通过MySQL官方命令行执行上述Hint语句,请在命令行中加上-c参数,否则该Hint会被MySQL官方命令行过滤导致Hint失效,具体请参见MySQL官方命令行
    • Hint的路由优化级最高,不受一致性级别和事务拆分的约束,使用前请进行评估。
    • Hint语句里不要有改变环境变量的语句,例如/*FORCE_SLAVE*/ set names utf8; 等,这类语句可能导致后续的业务出错。