18.5.3 事务一致性保证

术语说明
Primary:主(服务器或成员)
Secondary:从(属),次级或辅助(服务器或成员)

18.5.3 事务一致性保证

分布式系统(如组复制)的一个主要影响是它作为一个组提供的一致性保证。换句话说,分布在组成员之间的事务的全局同步的一致性。本节介绍组复制如何根据组中发生的事件处理一致性保证,以及如何最佳配置组的一致性保证。

18.5.3.1 理解事务一致性保证

分布式一致性保证而言,无论是在正常操作还是故障修复操作中,组复制始终是最终一致性系统。这意味着一旦传入流量减慢或停止,所有组成员都具有相同的数据内容。与系统一致性相关的事件可分为手动或由故障自动触发的控制操作,以及数据流操作

对于组复制,可以根据一致性评估的控制操作包括:

  • 成员加入或离开,这在组复制的 第18.5.4节“分布式恢复” 和写保护中有所涉及。
  • 网络故障,由**围栏模式(fencing mode)**覆盖。
  • 在单主组中,也可以使用group_replication_set_as_primary()触发主故障切换。

一致性保证和主故障切换

在单主组中,如果发生主故障切换,从升级为主,无论复制积压工作有多大,新的主都可以立即与应用程序通信,或者可以在积压工作被应用之前限制对其的访问。

使用第一种方法,该组在主故障后,通过选择一个新主,并立即允许数据访问,尽管它仍然应用来自旧主的任何可能积压,以花费尽可能短的时间确保稳定的组成员关系。写入一致性得到保证,但在新主应用积压工作时,读取可以暂时检索到过时的数据。例如,如果客户端 C1 在其故障之前在旧主上写入A=2 WHERE A=1,则当客户端 C1 重新连接到新主时,它可能会读取A=1,直到新主应用完它的积压工作并在旧主脱离组之前赶上旧主的状态。

对于第二种备选方案,系统在主要故障后确保稳定的组成员关系,并以与第一种备选方案相同的方式选择新主,但在这种情况下,组等待,直到新主完成所有的积压工作,然后才允许数据访问。这确保了在如上所述的情况下,当客户端 C1重新连接到新主时,它的读数为a=2。然而,代价是,故障切换所需的时间与积压(工作)的大小成正比,在正确配置的组中,积压的大小应该很小。

在 MySQL 8.0.14 之前,无法配置故障切换策略,默认情况下,采用如第一种方法所述的可用性最大化。在成员运行 MySQL 8.0.14 或更高版本的组中,可以使用 group_replication_consistency 变量配置成员在主故障切换期间提供的事务一致性保证级别。参见 一致性对选主的影响

数据流操作

由于对组执行读写操作,数据流与组一致性保证相关,特别是当这些操作分布在所有成员中时。数据流操作适用于组复制的两种模式:单主模式和多主模式,但为了更清楚地解释,此处仅以单主模式为例。在单主组的成员之间拆分传入的读或写事务的通常方法是将写操作路由到主成员,并将读操作平均分配到辅助(或从)成员。由于组应该作为一个单独的实体运行,因此可以合理地预期,主服务器上的写操作在辅助服务器上立即可用。尽管组复制是使用实现 Paxos 算法的组通信系统(GCS)协议编写的,但组复制的某些部分是异步的,这意味着数据是异步应用于辅助设备的。这意味着客户端 C2 可以在主服务器上写入B=2 WHERE B=1,立即连接到辅助服务器并读取B=1。这是因为辅助服务器仍在应用积压工作(backlog),并且尚未应用主服务器应用的事务。

事务同步点

您可以根据要在组内同步事务的点来配置组的一致性保证。为了帮助您理解这一概念,本节将同步组内事务的点简化为在读操作或写操作时。

如果在读取时同步数据,则当前客户端会话将等待直到一个给定的时间点,在该时间点所有先前的更新事务都已应用,然后才开始执行。使用此方法,仅此会话受影响,所有其他并发数据操作都不受影响。

如果在写入时同步数据,则写入会话将等待,直到所有辅助服务器都写入了数据。组复制在写入时使用绝对顺序,因此这意味着需等待此写入(对主的写入)以及从的队列中所有的先前写入被应用。因此,当使用此同步点时,写入会话将等待所有从的队列被应用。

任何替代方案确保在客户端 C2 所描述的场景下,即使立即连接到辅助,也始终读取B=2。每个备选方案都有其优点和缺点,这些都与您的系统工作负载直接相关。以下示例描述了不同类型的工作负载,并建议哪个同步点是合适的。

在这些情况下,您应该选择在写入时同步:

  • 为了避免读取过时的数据,您希望在不部署额外限制的情况下对读取进行负载均衡,组写入比组读取更不常见。
  • 如果您有一个以只读数据为主的组,那么您希望在提交后将读写事务应用于所有位置,以便对包括最新写入的最新数据进行后续读取。这确保您不必为每个 RO 事务负担同步成本,而只需为 RW 事务负担同步成本。

在这些情况下,您应该选择在读取时同步:

  • 为了避免读取过时的数据,您希望在不部署额外限制的情况下对读取进行负载均衡,组写入比组读取更常见。
  • 您希望工作负载中的特定事务始终从组中读取最新数据,例如,每当更新敏感数据(如文件的证书或类似数据)时,您希望强制执行读取操作以检索最新的值。

18.5.3.2 配置事务一致性保证

尽管“事务同步点”部分解释了从概念上讲,有两个同步点可供选择:读或写,但这些术语是简化的,组复制中使用的术语是:事务执行之前和之后。一致性级别可能会对组处理的只读(RO)和读写(RW)事务产生不同的影响,如本节所示。

以下列表显示了可以使用 group_replication_consistency 变量在组复制中配置的可能的一致性级别,以提高事务一致性保证:

  • EVENTUAL
    RO 和 RW 事务在执行之前都不会等待之前的事务被应用。这是添加 group_replication_consistency 变量之前组复制的行为。RW 事务不会等待其他成员应用事务。这意味着事务可以先外部化到一个成员,然后再外部化到其他成员。这也意味着,在主故障切换的情况下,新主可以在应用所有旧主事务以前就接受新的 RO 和 RW 事务。RO 事务可能会导致值过时,RW 事务可能会由于冲突而导致回滚。

  • BEFORE_ON_PRIMARY_FAILOVER
    新当选的主正在应用旧主的积压工作,在应用了所有积压工作之前,将保持(不应用)新主上的这些新的 RO 和 RW 事务。这确保了无论是否有意发生主故障切换,客户端都能看到主故障切换上的最新值。这保证了一致性,但意味着客户端必须能够在应用积压工作时处理延迟。通常这种延迟应该是最小的,但它确实取决于积压工作的规模。

  • BEFORE
    RW 事务在被应用以前等待所有之前的事务完成。RO 事务在被执行以前等待所有之前的事务完成。这确保该事务仅通过影响事务的延迟来读取最新值。这通过确保仅在 RO 事务上使用同步,减少了每个 RW 事务上的同步开销。此一致性级别还包括 BEFORE_ON_PRIMARY_FAILOVER 提供的一致性保证。

  • AFTER
    RW 事务等待其更改应用于所有其他成员。该值对 RO 事务没有影响。此模式确保在本地成员上提交事务时,任何后续事务都会读取写入的值或任何组成员上的最新值。将此模式与主要用于 RO 操作的组一起使用,以确保应用的 RW 事务在提交后应用于所有位置。您的应用程序可以使用它来确保后续读取获取包括最新写入的最新数据。这通过确保仅在 RW 事务上使用同步,减少了每个 RO 事务上的同步开销。此一致性级别还包括 BEFORE_ON_PRIMARY_FAILOVER 提供的一致性保证。

  • BEFORE_AND_AFTER
    RW 事务等待 1)在被应用以前完成所有之前的事务,2)直到其更改应用于其他成员。RO 事务在执行之前等待所有前面的事务完成。此一致性级别还包括 BEFORE_ON_PRIMARY_FAILOVER 提供的一致性保证。

BEFOREBEFORE_AND_AFTER 一致性级别可以同时用于 RO 和 RW 事务。AFTER 一致性级别对 RO 事务没有影响,因为它们不会产生更改。

如何选择一致性级别

不同的一致性级别为使用它们来建立基础设施的 DBA ,和能够使用最适合其应用程序需求的一致性级别的开发人员,提供了灵活性。以下场景显示了如何根据您使用组的方式选择一致性保证级别:

  • 场景 1 :如果要在不用担心过时读取的情况下负载均衡读取,则组写操作要比组读操作少得多。在这种情况下,您应该选择 AFTER
  • 场景 2 :您有一个应用大量写入的数据集,您希望偶尔进行读取,而不必担心读取过时的数据。在这种情况下,您应该选择 BEFORE
  • 场景 3 :您希望工作负载中的特定事务始终从组中读取最新数据,以便每当更新敏感数据(例如文件的证书或类似数据)时,您都希望强制读取始终读取最新的值。在这种情况下,您应该选择 BEFORE
  • 场景 4 :如果您有一个以只读(RO)数据为主的组,您希望在提交后将读写(RW)事务应用于所有位置,以便后续读取包括最新写入的最新数据,只需为 RW 事务而不必为 RO 事务的同步付出代价。在这种情况下,您应该选择 AFTER
  • 场景 5 :如果您有一个以只读数据为主的组,您希望您的读写(RW)事务始终从组中读取最新数据,并在提交后应用于所有位置,以便后续读取包括您最新写入的最新数据。您不必为每个只读(RO)事务同步付出代价,而只需为 RW 事务同步付出代价。在这种情况下,您应该选择 BEFORE_AND_AFTER

您可以自由选择执行一致性级别的范围。这很重要,因为如果在全局范围内设置一致性级别,则一致性级别可能会对组性能产生负面影响。因此,您可以通过在不同范围使用 group_replication_consistency 系统变量来配置组的一致性级别。

要在当前会话上强制执行一致性级别,请使用会话范围:

> SET @@SESSION.group_replication_consistency= 'BEFORE';

要在所有会话上强制执行一致性级别,请使用全局范围:

> SET @@GLOBAL.group_replication_consistency= 'BEFORE';

在特定会话上设置一致性级别的可能性使您能够利用以下场景:

  • 场景 6 :给定的系统处理几个不需要强一致性级别的指令,但有一种指令确实需要强一致:管理对文档的访问权限。在这种情况下,系统会更改访问权限,并希望确保所有客户端都看到正确的权限。您只需要执行SET @@SESSION.group_replication_consistency= ‘AFTER’”,并让其他指令在全局范围内设置 EVENTUAL 的情况下运行。

  • 场景 7 :在与 场景 6 中描述的相同系统上,每天一条指令都需要进行一些分析处理,因此它需要始终读取最新的数据。要实现这一点,在运行该特定指令的会话中只需执行SET @@SESSION.group_replication_consistency= ‘BEFORE’

总之,您不需要使用同一特定的一致性级别运行所有事务,特别是如果只有某些事务实际上需要它。

请注意,所有读写事务在组复制中都是绝对有序的,因此即使您将当前会话的一致性级别设置为 AFTER ,该事务也会等待,直到其更改应用于所有成员,这意味着等待此事务和可能在从()成员)的队列中的所有先前事务。在实践中,一致性级别 AFTER 一直等待,直到包括此事务在内的所有事务结束。

一致性级别的影响

对一致性级别进行分类的另一种方法是根据对组的影响,即一致性级别对其他成员的影响。

BEFORE 一致性级别除了在事务流上排序之外,只影响本地成员。也就是说,它不需要与其他成员协调,也不会对他们的事务产生影响。换句话说,BEFORE 只影响使用它的事务。

AFTERBEFORE_AND_AFTER 一致性级别确实会对其他成员上执行的并发事务产生副作用。当 AFTERBEFORE_AND_AFTER 事务正在执行时,如果 EVENTUAL 一致性级别的事务开始,这些一致性级别会使其他成员事务等待。其他成员等待直到在该成员上提交 AFTER 事务,即使其他成员的事务具有 EVENTUAL 一致性级别。换句话说,AFTERBEFORE_AND_AFTER 影响所有在线组成员。

为了进一步说明这一点,设想一个有 3 个成员的组,M1 、M2 和M3 。在成员 M1 上,客户端执行:

> SET @@SESSION.group_replication_consistency= AFTER;
> BEGIN;
> INSERT INTO t1 VALUES (1);
> COMMIT;

然后,当正在应用上述事务时,在成员 M2 上,客户机发出:

> SET SESSION group_replication_consistency= EVENTUAL;

在这种情况下,即使第二个事务的一致性级别是 EVENTUAL ,因为它在第一个事务在 M2 上已经处于的提交阶段时开始执行,第二个事务必须等待第一个事务完成提交,然后才能执行。

只能在 ONLINE 成员上使用一致性级别 BEFOREAFTERBEFORE_AND_AFTER ,尝试在其他状态的成员上使用它们会导致会话错误。

一致性级别不是 EVENTUAL 的事务将保持执行,直到达到由 wait_timeout 值配置的超时(默认为 8小时)。如果达到超时,将引发ER_GR_HOLD_WAIT_TIMEOUT 错误。

一致性对选主的影响

本节介绍组的一致性级别如何影响已选择新主的单主组。这样的组自动检测故障并调整活动成员的视图,换句话说,成员配置。此外,如果某个组以单主模式部署,则每当该组的成员身份发生更改时,都会执行检查以检测该组中是否仍有主成员。如果没有,则从次级成员列表中选择一个新成员。通常,这被称为次级晋升(secondary promotion)

考虑到系统自动检测故障并重新配置自身的事实,用户还可以预期,一旦升级发生,新的主在数据方面与旧的主处于完全相同的状态。换言之,一旦用户能够读取和写入新的主,他可能会期望没有要应用于新的主的积压的复制事务。实际上,用户可能会期望,一旦他的应用程序故障转移到新的主,就不会读取(即使是暂时的读取)旧数据或写入旧数据记录。

当流量控制被激活并对某个组进行了适当调整时,在晋升后立即从新当选的主中暂时读取过时数据的可能性很小,因为不应该有积压,或者如果有积压,则应该很小。此外,您可能有一个代理或中间件层来管理晋升后对主的访问,并在该级别强制执行一致性标准。如果您的组成员使用的是 MySQL 8.0.14 或更高版本,则可以使用 group_replication_consistency 变量指定新主晋升后的行为,该变量控制新选举的主在完全应用积压工作之前是否同时阻止读和写,或者其行为是否与运行 MySQL 8.0.13 或更早版本的成员相同。如果在新选举的主上有积压工作要应用, group_replication_consistency 选项设置为 BEFORE_ON_PRIMARY_FAILOVER ,并且在新主仍在应用积压工作时针对新主发起事务,则传入事务将被阻止,直到积压工作完全应用。因此,可防止以下异常:

  • 只读和读写事务没有过时的读取。这可以防止新的主应用程序将过时的读取外部化到应用程序。

  • 读写事务没有虚假回滚,因为写写冲突与复制的读写事务仍在等待应用的积压工作中。

  • 读写事务没有读取偏差,例如:

    > BEGIN;
    > SELECT x FROM t1; -- x=1 because x=2 is in the backlog;
    > INSERT x INTO t2;
    > COMMIT;
    

    此查询不应导致冲突,但应写入过时的值。

总之,当 group_replication_consistency 设置为 BEFORE_ON_PRIMARY_FAILOVER 时,您选择将一致性优先于可用性,因为每当选择新的主节点时,都会执行读写操作。这是您在配置组时必须考虑的权衡。还应该记住,如果流控制工作正常,积压工作应该是最小的。请注意, BEFORE_ON_PRIMARY_FAILOVERAFTERBEFORE_AND_AFTER 这些较高的一致性级别还包括 BEFORE_ON_PRIMARY_FAILOVER 提供的一致性保证。

为了确保组提供相同的一致性级别,无论哪个成员升级为主成员,组的所有成员都应将 BEFORE_ON_PRIMARY_FAILOVER (或更高的一致性等级)持久化到其配置。例如,在每个成员上执行:

> SET PERSIST group_replication_consistency='BEFORE_ON_PRIMARY_FAILOVER';

这确保了所有成员都以相同的方式运行,并且在重新启动成员后保持配置。

事务不能永远保持,如果保持的时间超过 wait_timeout ,则返回ER_GR_HOLD_WAIT_TIMEOUT 错误。

一致性规则下允许的查询

尽管在使用 BEFORE_ON_PRIMARY_FAILOVER 一致性级别时保持了所有的写入,但并不是所有的读取都被阻止,以确保在升级后应用积压工作时仍可以检查服务器。这对于调试、监视、可观察性和故障排除非常有用。允许某些不修改数据的查询,例如:

  • SHOW语句——从 MySQL 8.0.27 开始,这仅限于那些不依赖数据、仅依赖状态和配置的语句,如下所示。
    SHOW自 MySQL 8.0.27 以后允许的包括:SHOW VARIABLES, SHOW PROCESSLIST, SHOW STATUS, SHOW ENGINE INNODB LOGS, SHOW ENGINE INNODB STATUS, SHOW ENGINE INNODB MUTEX, SHOW MASTER STATUS, SHOW REPLICA STATUS, SHOW CHARACTER SET, SHOW COLLATION, SHOW BINARY LOGS, SHOW OPEN TABLES, SHOW REPLICAS, SHOW BINLOG EVENTS, SHOW WARNINGS, SHOW ERRORS, SHOW ENGINES, SHOW PRIVILEGES, SHOW PROCEDURE STATUS, SHOW FUNCTION STATUS, SHOW PLUGINS, SHOW EVENTS, SHOW PROFILE, SHOW PROFILES, SHOW RELAYLOG EVENTS
  • SET语句
  • 不使用表或可加载函数的DO语句
  • EMPTY 语句
  • USE语句
  • performance_schemasys数据库使用的SELECT语句
  • infoschema数据库中的PROCESSLIST表使用SELECT语句
  • 不使用表或可加载函数的SELECT语句
  • STOP GROUP_REPLICATION语句
  • SHUTDOWN语句
  • RESET PERSIST语句
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独上西楼影三人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值