数据库代理的读写分离能力,会解析发送进来的每一条 SQL,如果是 UPDATE、DELETE、INSERT、CREATE 等写操作则直接发往主节点,如果是 SELECT 读操作则发送到只读节点,从而实现读写分离。但是当数据库负载很高时,例如对大表执行 DDL(如加字段)操作或大批量插入数据的时候,数据同步延迟会非常高,从而导致无法从只读节点中读取到最新数据。读写分离代理功能无法解决由于延迟导致的查询不一致问题。
读写节点有数据写入后,相关的更新会同步到只读节点,其中数据同步的延迟时间与写入压力有关。云数据库 veDB MySQL 版通过提供不同的一致性级别,来保证业务访问数据库的数据一致性要求。
说明
一致性级别从最终一致性的调整到会话一致性或全局一致性,仅对新连接生效。从会话一致性或全局一致性调整到最终一致性,存量连接立即生效。操作步骤请参见编辑连接终端。 最终一致性
功能介绍
云数据库 veDB MySQL 版提供自动读写分离的能力,默认提供数据的最终一致性级别,从而保证只读节点最终都能读取到已更新的数据。但最终一致性不能保证立即读取到最新的数据,因为主从复制延迟会导致从不同节点查询到的结果不同,例如在一个会话内连续执行查询操作,最后 SELECT 的结果可能会不同。
适用场景
对一致性要求不是很高的场景可以选择最终一致性,通过读写分离的能力,减轻主节点的压力,让读请求尽可能路由到只读节点。
会话一致性
功能介绍
由于最终一致性无法保证一个会话内连续执行查询的结果相同,因此无法满足对一致性要求高的场景。在这种情况下,就需要对业务进行拆分,对一致性要求高的业务,只访问读写节点,对一致性要求不高的业务可以采用读写分离模式。为了进一步降低业务改造的负担,veDB MySQL 提供会话一致性的能力。会话一致性保证了同一个会话内,一定能够查询到读请求执行前已更新的数据。在本会话更新后,到本会话或其他会话再次更新之前,读到的结果是稳定的。
在 veDB MySQL 的链路中,数据库代理提供读写分离的能力,会话一致性的实现主要是依赖于数据库代理。
- 数据库代理会记录每个节点已经应用的日志位点,即日志序号(Log Sequence Number,简称 LSN)。
- 每次读写事务提交时 veDB MySQL 会记录此次更新的位点为 Session LSN。
- 当有读请求到来时, 数据库代理会用 Session LSN 和当前各个节点的 LSN 做比较。
- 仅将请求发往 LSN 大于或等于 Session LSN 的读节点,从而保证了会话一致性。
由于数据库代理节点会比较只读节点 LSN 的推进位置,因此在主从节点延迟很大的情况下,业务无法一直等待,会影响整体性能。所以 veDB MySQL 支持配置超时时间阈值以及超时后的策略。
- 配置超时阈值:默认值为 10000us,取值范围为 1us~100000000us。
- 发送请求到主节点:如果主从延迟过大,配置的超时阈值较小,会将读请求发往主节点,增加主节点压力。
- SQL 报错:如果主从延迟过大,超过阈值,则会直接返回报错:wait replication complete timeout, please retry。
在上示例述场景中,当更新完成后,返回结果时,数据复制已经开始。所以当下一个读请求到来时,主节点和只读节点之间的数据复制极有可能已经完成,即只读节点可以提供最新的数据查询。所以在这种架构下既保证了会话一致性,又保证了读写分离负载均衡的效果。
适用场景
适用于一致性要求较高的场景,该级别对性能影响很小而且能满足绝大多数应用场景的需求。
全局一致性
功能介绍
对于所有会话之间可能存在因果关系或依赖关系的场景,会话一致性将无法保证查询结果的一致性。因此 veDB MySQL 也提供了全局一致性的能力。当每个读请求到达数据库代理后,代理都会先去主节点确认当前最新的 COMMIT LSN 位点,然后找到一个合适的只读节点,再将读请求发送至该只读节点。这样就能保证该读请求能够读到至请求发起时刻为止,任意一条已完成更新的数据。
同样为了保证业务的正常使用,全局一致性也支持配置超时时间阈值和超时后的策略。
- 配置超时阈值:默认值为 10000us,取值范围为 1us~100000000us。
- 发送请求到主节点:如果主从延迟过大,配置的超时阈值较小,会将读请求发往主节点,增加主节点压力。
- SQL 报错:如果主从延迟过大,超过阈值,则会直接返回报错:wait replication complete timeout, please retry。
适用场景
当主从延迟较高时,只读节点无法及时同步最新的数据,可能会导致更多的请求被路由到主节点,造成主节点压力增大。因此建议在读多写少的场景下选择全局一致性。
- 一致性级别越高,实例性能越低。因此推荐使用会话一致性,该级别对性能影响很小,而且能满足绝大多数应用场景的需求。
- 尽量避免选择全局一致性。若有少量业务逻辑需要全局一致性时,可通过 Hint 强制将相应请求路由至主节点。关于 Hint 的使用详情请参见 Hint 语法使用。