Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Configuring Transaction Consistency Guarantees

20.5.3.2 配置事务一致性保证

虽然事务同步点部分解释了概念上有两个同步点可以选择:读取或写入,这些术语是简化的,Group Replication 中使用的是:beforeafter 事务执行。事务一致性级别对只读(RO)和读写(RW)事务可能会产生不同的影响,如本节所示。

以下是使用group_Replication_consistency变量配置的可能一致性级别列表,按递增的事务一致性保证顺序排列:

  • EVENTUAL

    RO 和 RW 事务都不等待前一个事务被应用后执行。这是 Group Replication 在添加group_Replication_consistency变量之前的行为。RW 事务不等待其他成员应用事务。这意味着在一个成员上可以在其他成员之前外部化事务。这也意味着,在主服务器故障转移时,新的主服务器可以接受新的事务 RO 和 RW 事务,而不是等待前一个主服务器的事务都被应用。RO 事务可能导致 outdated 值,RW 事务可能导致冲突 rollback。

  • BEFORE_ON_PRIMARY_FAILOVER

    新选举的主服务器正在应用老主服务器的 backlog 的 RO 或 RW 事务将被保留(不被应用)直到 backlog 完全被应用。这确保了在主服务器故障转移时,客户端总是可以看到最新值。这个保证一致性,但意味着客户端必须能够处理延迟,因为 backlog 应用可能需要一些时间。通常,这个延迟应该很小,但是它取决于 backlog 的大小。

  • BEFORE

    RW事务等待所有前置事务完成后才被应用。RO事务等待所有前置事务完成后才被执行。这确保了该事务只读取最新值,而不是影响事务的延迟。这减少了每个RW事务的同步开销,只在RO事务中使用同步。这一致性级别还包括BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。

  • AFTER

    RW事务等待其更改被应用到所有其他成员。这对RO事务没有影响。这一模式确保了当在本地成员上提交事务时,任何后续事务都可以读取写入值或更 recent 值在任何组成员上。使用该模式与主要用于RO操作的组来确保已提交RW事务被应用到所有地方。这可以由您的应用程序使用,以确保后续读取 fetch 最新的数据,这包括最新的写入。这减少了每个RO事务的同步开销,只在RW事务中使用同步。这一致性级别还包括BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。

  • BEFORE_AND_AFTER

    RW事务等待1) 所有前置事务完成后才被应用和2) 直到其更改被应用于其他成员。RO事务等待所有前置事务完成后才执行。这一致性级别还包括BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。

RO 和 RW 事务都可以使用 BEFOREBEFORE_AND_AFTER 一致性级别,而 AFTER 一致性级别对 RO 事务没有影响,因为它们不生成变化。

不同的一致性级别为 DBA 和开发者提供了灵活性,可以根据他们的应用程序需求选择合适的一致性级别。以下场景展示了如何根据使用组的方式选择一致性保证级别:

  • Scenario 1 您想在不考虑 stale reads 的情况下负载均衡读取操作,而您的写操作远少于读操作。在这种情况下,您应该选择 AFTER

  • Scenario 2 您有一个需要大量写入的数据集,并且想要在不考虑 stale data 的情况下 occasional 读取。在这种情况下,您应该选择 BEFORE

  • Scenario 3 您想确保特定的事务始终从组中读取最新的数据,以便在敏感数据更新时(例如文件凭证或类似数据)您可以强制 reads 始终读取最新值。在这种情况下,您应该选择 BEFORE

  • 场景4 您有一个主要读取只读数据的组,想要在写入事务提交后应用写入事务到所有地方,以便后续读取操作可以从最新写入的数据中读取,并且不需要在每个只读事务上支付同步开销,只在写入事务上支付。这种情况下,您应该选择AFTER

  • 场景5 您有一个主要读取只读数据的组,想要在写入事务提交后应用写入事务到所有地方,并且总是从组中读取最新的数据,以便后续读取操作可以从最新写入的数据中读取,并且不需要在每个只读事务上支付同步开销,只在写入事务上支付。这种情况下,您应该选择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’

总之,您不需要将所有事务设置为特定的一致性级别,特别是如果只有少数事务实际需要它。

注意,在Group Replication中,所有读写事务都是完全有序的,因此,即使您将会话设置为AFTER,这笔交易也会等待其更改被应用于所有成员,这意味着等待该事务和所有前置事务在次要节点队列中。实际上,AFTER一致性级别等待的是从该事务开始到包括该事务的所有事务。

还有一种将一致性级别分类的方法是根据其对组的影响,即一致性级别对其他成员的后果。

在事务流中排序之外,BEFORE一致性级别仅对本地成员产生影响,即不需要与其他成员协调,也不会影响他们的事务。换言之,BEFORE只影响使用它的交易。

AFTERBEFORE_AND_AFTER一致性级别则会对并发事务产生影响,这些事务在其他成员上执行。如果一个事务使用EVENTUAL一致性级别开始,而另一个事务正在使用AFTERBEFORE_AND_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错误。

本节描述了单主组中的一致性级别如何影响新的主节点的选举。这种组自动检测故障并调整活动成员的视图,即成员配置。此外,如果组在单主模式下,任何时候成员列表发生变化都会检查是否仍有主节点。如果没有,则从次要成员列表中选择一个新的主节点。这通常称为次要升级。

考虑到系统自动检测故障并重新配置自己,您也可能期望在升级完成后,新主节点的状态与旧主节点相同,从数据角度。换言之,您可能期望升级完成后,新主节点上没有未复制的事务需要应用。在实际情况下,您可能期望在应用程序失败转移到新主节点时,不会出现读取老数据或写入老数据记录的机会,即使是暂时的。

在群组中启用流量控制并正确调整后,只有很小的可能性会从新选举的主服务器中读取暂时的 stale 数据,这是因为没有或只有少量的 backlog。另外,您可能拥有代理或中间件层,用于管理应用程序对主服务器的访问,并在该级别强制执行一致性标准。您可以使用group_ replication_consistency变量来控制新选举的主服务器在被提升后的一些行为。如果group_ replication_consistency变量设置为BEFORE_ON_PRIMARY_FAILOVER,新选举的主服务器在应用 backlog 之前不会处理事务,因此以下异常情况将被防止:

  • 对只读和读写事务没有 stale 读取。这可以防止新主服务器外部化 stale 读取给应用程序。

  • 对读写事务没有虚假回滚,这是由于与已在 backlog 中等待被应用的复制读写事务发生写写冲突所致。

  • 对读写事务没有读取不一致,例如:

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

    这查询不会导致冲突,但却会将 outdated 值写入。

总的来说,当group_replication_consistency设置为BEFORE_ON_PRIMARY_FAILOVER时,您选择了在新主服务器选举时优先考虑一致性,而不是可用性,因为读取和写入操作将被暂停。这是您在配置组时需要考虑的权衡。同时,需要注意的是,如果流量控制正确,回滚应该很小。需要注意的是,高级的一致性级别BEFOREAFTERBEFORE_AND_AFTER也包括了BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。

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

> SET PERSIST group_replication_consistency='BEFORE_ON_PRIMARY_FAILOVER';

这确保了所有成员都按照相同的方式行为,并且在成员重启后,配置将被 persist。

事务不能永远保持挂起状态,如果超出了wait_timeout时间,它将返回一个ER_GR_HOLD_WAIT_TIMEOUT错误。

虽然在使用BEFORE_ON_PRIMARY_FAILOVER一致性级别时所有写操作都被持有,但不是所有读操作都被阻塞,以确保可以在服务器应用 backlog 后的promotion过程中继续检查服务器。这对调试、监控、可观察性和故障排除非常有用。一些不修改数据的查询语句是允许的,例如:

  • SHOW 语句:这只限于不依赖数据、只依赖状态和配置的语句,以下列举:

  • SET 语句

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

  • EMPTY 语句

  • USE 语句

  • 使用SELECT 语句查询performance_schemasys数据库

  • 使用SELECT 语句查询PROCESSLIST表来自infoschema数据库

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

  • STOP GROUP_REPLICATION 语句

  • SHUTDOWN 语句

  • RESET PERSIST 语句

允许的SHOW语句是:SHOW VARIABLESSHOW PROCESSLISTSHOW STATUSSHOW ENGINE INNODB LOGSSHOW ENGINE INNODB STATUSSHOW ENGINE INNODB MUTEXSHOW BINARY LOG STATUSSHOW REPLICA STATUSSHOW CHARACTER SETSHOW COLLATIONSHOW BINARY LOGSSHOW OPEN TABLESSHOW REPLICASSHOW BINLOG EVENTSSHOW WARNINGSSHOW ERRORSSHOW ENGINESSHOW PRIVILEGESSHOW PROCEDURE STATUSSHOW FUNCTION STATUSSHOW PLUGINSSHOW EVENTSSHOW PROFILESHOW PROFILES,和SHOW RELAYLOG EVENTS