一致性级别

PolarDB提供了四种一致性级别:最终一致性、会话一致性、全局一致性和全局一致性(高性能模式),满足您在不同场景下对一致性级别的要求。

问题与解决方案

MySQL的读写分离代理功能,代理会伪造成MySQL与应用程序建立好连接,解析发送进来的每一条SQL,如果是UPDATE、DELETE、INSERT、CREATE等写操作则直接发往主库,如果是SELECT则发送到备库,从而实现了读写分离。但是当数据库负载很高时,例如对大表执行DDL(如加字段)操作或大批量插入数据的时候,延迟会非常严重,从而导致无法从只读节点中读取最新数据。MySQL的读写分离代理功能无法解决由于延迟导致的查询不一致问题。

PolarDB采用了异步物理复制方式实现了主节点和只读节点间的数据同步。主节点的数据更新后,相关的更新会应用到只读节点,具体的延迟时间与写入压力有关(一般在毫秒级别),通过异步复制的方式确保了主节点和只读节点间数据的最终一致。PolarDB提供了如下四种一致性级别,满足您在不同场景下对一致性级别的要求:

最终一致性

  • 功能介绍

    PolarDB是读写分离的架构,传统的读写分离只提供最终一致性的保证,主从复制延迟会导致从不同节点查询到的结果不同,例如在一个会话内连续执行如下查询,最后的SELECT结果可能会不同(具体的访问结果由主从复制的延迟决定)。

    INSERT INTO t1(id, price) VALUES(111, 96);
    UPDATE t1 SET price = 100 WHERE id=111;
    SELECT price FROM t1;
  • 适用场景

    若需要减轻主节点压力,让尽量多的读请求路由到只读节点,您可以选择最终一致性。

会话一致性

  • 功能介绍

    针对最终一致性导致查询结果不同的问题,通常需要将业务进行拆分,将一致性要求高的请求直接发往主节点,而可以接受最终一致性的请求则通过读写分离发往只读节点。这既增加了主节点的压力,影响读写分离的效果,又增加了应用开发的负担。

    为解决上述问题,PolarDB提供了会话一致性(也称因果一致性)。会话一致性保证了同一个会话内,一定能够查询到读请求执行前已更新的数据,确保了数据单调性。

    PolarDB的链路中间层做读写分离的同时,中间层会追踪各个节点已经应用的Redo日志位点,即日志序号(Log Sequence Number,简称LSN)。同时每次数据更新时PolarDB会记录此次更新的位点为Session LSN。当有新请求到来时,PolarDB会比较Session LSN和当前各个节点的LSN,如果只读节点的LSN不满足,会根据您配置的超时时间等待只读节点同步到最新数据,仅将请求发往LSN大于或等于Session LSN的节点,从而保证了会话一致性。表面上看该方案可能导致主节点压力大,但是因为PolarDB是物理复制,速度极快。

    4

    在上述场景中,当更新完成后,返回客户端结果时复制就同步在进行,而当下一个读请求到来时,主节点和只读节点之间的数据复制极有可能已经完成。且大多数应用场景都是读多写少,所以经验证在该机制下既保证了会话一致性,又保证了读写分离负载均衡的效果。

  • 适用场景

    PolarDB的一致性级别越高,对主库的压力越大,集群性能也越低。推荐使用会话一致性,该级别对性能影响很小而且能满足绝大多数应用场景的需求。

全局一致性

  • 功能介绍

    在部分应用场景中,除了会话内部有逻辑上的因果依赖关系,会话之间也存在依赖关系,例如在使用连接池的场景下,同一个线程的请求有可能通过不同连接发送出去。对数据库来说这些请求属于不同会话,但是业务逻辑上这些请求有前后依赖关系,此时会话一致性便无法保证查询结果的一致性。因此PolarDB提供了全局一致性来解决该问题。

    会话间存在的依赖关系

    每个读请求到达PolarDB数据库代理时,代理都会先去主节点确认当前最新的LSN位点,假设为LSN0(为了减少每次读请求都去获得主节点的最新LSN,内部做了批量优化), 然后等待所有只读节点的LSN都更新至主节点的LSN0位点后,代理再将读请求发送至只读节点。这样就能保证该读请求能够读到至请求发起时刻为止,任意一条已完成更新的数据。

    全局一致性提供如下两个配置参数:

    参数

    说明

    ConsistTimeout

    全局一致性读超时时间,读请求等待只读节点同步LSN(位点)的最长时间。若超出该时间,PolarDB代理将根据ConsistTimeoutAction参数设置进行对应操作。

    取值范围:0~60000。默认值为20。单位为毫秒。

    ConsistTimeoutAction

    全局一致性读超时策略,若未能在参数ConsistTimeout设置的时间内将只读节点的LSN更新至主节点最新LSN,PolarDB代理将根据ConsistTimeoutAction参数设置进行对应操作。

    取值范围如下:

    • 0(默认):将读请求发送到主节点。

    • 1:代理返回一个错误报文wait replication complete timeout, please retry给应用端。

    说明

    如何修改全局一致性读超时时间全局一致性读超时策略,请参见配置数据库代理

  • 适用场景

    当主从延迟较高时,使用全局一致性可能会导致更多的请求被路由到主节点,造成主节点压力增大,业务延迟也可能增加。因此建议在读多写少的场景下选择全局一致性。

全局一致性(高性能模式)

PolarDB MySQL版推出了全局一致性(高性能模式)服务。全局一致性(高性能模式)具有比全局一致性更严格的强一致性要求。

PolarTrans事务系统利用提交时间戳技术CTS和RDMA网络,在纯内核层面提供RO节点强一致性读服务,从而保证始终能看到RW和RO节点最新的数据,提供了集群维度的强一致性读能力,保证发往集群任意副本的读请求都可以获得强一致性的结果。

关于全局一致性(高性能模式)的更多细节(如使用限制、技术原理、开启方式以及性能数据等),请参见全局一致性(高性能模式)

如何选择一致性级别

  • PolarDB一致性级别越高,集群性能越低。

    推荐使用会话一致性,该级别对性能影响很小而且能满足绝大多数应用场景的需求。

  • 若对不同会话间的一致性需求较高,可以选择如下方案之一:

    • 选择全局一致性(高性能模式)全局一致性

      说明
      • 对于PolarDB MySQL版5.7、8.0.1和8.0.2版本,若追求严格强一致性,更推荐全局一致性(高性能模式)。

      • 对于PolarDB MySQL版5.6版本,若追求严格强一致性,由于该版本暂不支持全局一致性(高性能模式),可选择全局一致性

    • 使用HINT将特定查询强制发送至主节点执行。

      /*FORCE_MASTER*/ select * from user;
      说明
      • 若您需要通过MySQL官方命令行执行上述Hint语句,请在命令行中加上-c参数,否则该Hint会被MySQL官方命令行过滤导致Hint失效,具体请参见MySQL官方命令行

      • Hint的路由优先级最高,不受一致性级别和事务拆分的约束,使用前请进行评估。

      • Hint语句里不要有改变环境变量的语句,例如/*FORCE_SLAVE*/ set names utf8;等,这类语句可能导致后续的业务出错。

如何设置一致性级别