Documentation Home
MySQL 8.0 参考手册  / 第十八章 组复制  / 18.5 组复制操作  / 18.5.3 交易一致性保证  /  18.5.3.2 配置事务一致性保证

18.5.3.2 配置事务一致性保证

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

以下列表显示了您可以使用 group_replication_consistency 变量在 Group Replication 中配置的可能的一致性级别,以增加事务一致性保证的顺序:

  • EVENTUAL

    RO 和 RW 事务都不会在执行前等待前面的事务被应用。这是 group_replication_consistency 添加变量之前 Group Replication 的行为。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 事务在提交后随处应用。您的应用程序可以使用它来确保后续读取获取最新数据,其中包括最新写入。这减少了每个 RO 事务同步的开销,通过确保仅在 RW 事务上使用同步。此一致性级别还包括由 BEFORE_ON_PRIMARY_FAILOVER.

  • BEFORE_AND_AFTER

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

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

如何选择一致性级别

不同的一致性级别为两个 DBA 提供了灵活性,他们可以使用它们来设置他们的基础架构;以及可以使用最适合其应用程序要求的一致性级别的开发人员。以下场景展示了如何根据您使用组的方式选择一致性保证级别:

  • 场景 1您想要负载平衡您的读取而不用担心过时的读取,您的组写入操作比您的组读取操作少得多。在这种情况下,您应该选择 AFTER.

  • 场景 2您有一个应用大量写入的数据集,您希望偶尔进行读取而不必担心读取陈旧数据。在这种情况下,您应该选择BEFORE.

  • 场景 3您希望工作负载中的特定事务始终从组中读取最新数据,以便每当更新敏感数据(例如文件或类似数据的凭据)时,您希望强制读取始终读取最新的价值。在这种情况下,您应该选择 BEFORE.

  • 场景 4您有一个主要包含只读 (RO) 数据的组,您希望读写 (RW) 事务在提交后随处应用,以便后续读取对最新数据完成,其中包括您最近的写入,并且您无需为每个 RO 事务支付同步费用,而只需为 RW 事务支付同步费用。在这种情况下,您应该选择 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

  • 场景七在场景六描述的同一个系统上,每天一条指令需要做一些分析处理,因此它需要始终读取最新的数据。为此,您只需要执行SET @@SESSION.group_replication_consistency= ‘BEFORE’该特定说明即可。

总而言之,您不需要运行具有特定一致性级别的所有事务,尤其是在只有某些事务实际需要它的情况下。

请注意,所有读写事务在 Group Replication 中都是完全有序的,因此即使您将AFTER当前会话的一致性级别设置为,此事务也会等待直到其更改应用于所有成员,这意味着等待此事务和所有之前的事务可能在辅助队列中。实际上,一致性级别AFTER会等待所有事务,直到并包括此事务。

一致性水平的影响

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

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

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

为了进一步说明这一点,想象一个有 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 上的提交阶段,所以第二个事务必须等待第一个事务完成提交才能执行.

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

一致性级别为不 EVENTUAL执行的事务,直到wait_timeout 达到按值配置的超时(默认为 8 小时)。如果达到超时,ER_GR_HOLD_WAIT_TIMEOUT则会抛出错误。

一致性对初选的影响

本节描述组的一致性级别如何影响已选出新主组的单主组。这样的组会自动检测故障并调整活动成员的视图,换句话说就是成员配置。此外,如果组以单主模式部署,则每当组的成员身份发生变化时,都会执行检查以检测组中是否仍有主要成员。如果没有,则从次要成员列表中选择一个新成员。通常,这称为二次促销。

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

当流量控制在一个组上被激活和适当调整时,只有很小的机会在提升后立即从新选出的主节点暂时读取陈旧数据,因为不应该有积压,或者如果有积压应该很小. 此外,您可能有一个代理或中间件层来管理升级后应用程序对主服务器的访问,并在该级别强制执行一致性标准。如果您的组成员使用的是 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您选择将一致性优先于可用性时,因为只要选择新的主节点,就会保留读取和写入。这是您在配置组时必须考虑的权衡。还应该记住,如果流控制正常工作,积压应该是最小的。请注意,更高的一致性级别 BEFOREAFTERBEFORE_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 开始,这仅限于那些不依赖于数据,仅依赖于状态和配置的语句,如下所列

  • SET声明

  • DO不使用表或可加载函数的语句

  • EMPTY声明

  • USE声明

  • SELECT针对performance_schemasys数据库 使用语句

  • 对数据库 中的表 使用SELECT语句PROCESSLISTinfoschema

  • SELECT不使用表或可加载函数的语句

  • STOP GROUP_REPLICATION 声明

  • SHUTDOWN声明

  • RESET PERSIST声明

MySQL 8.0.27 允许的SHOW 语句是 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,and SHOW RELAYLOG EVENTS