尽管事务同步点部分解释了概念上有两个同步点可以选择:在读取或写入,这些术语是简化的,而在Group Replication中使用的术语是:before和after事务执行。一致性级别可以对只读(RO)和读写(RW)事务产生不同的影响,如本节所示。
以下列表显示了可以在Group Replication中使用group_replication_consistency
变量配置的一致性级别,以增加事务一致性保证的顺序:
-
EVENTUAL
RO和RW事务都不等待前一个事务应用之前执行。这是Group Replication在添加
group_replication_consistency
变量之前的行为。RW事务不等待其他成员应用事务。这意味着事务可能在一个成员上外部化,而其他成员尚未应用。这也意味着在主故障转移时,新的主可以在旧主事务全部应用之前接受新的RO和RW事务。RO事务可能会导致过时的值,RW事务可能会由于冲突而回滚。 -
BEFORE_ON_PRIMARY_FAILOVER
新的RO或RW事务在新的主选举中应用之前将被持有(不应用),直到任何积压都被应用。这确保了在主故障转移时,客户端总是看到最新的值。这种一致性保证,但客户端必须能够处理延迟,因为可能需要应用积压。
-
BEFORE
RW事务等待所有前一个事务完成之前应用。RO事务等待所有前一个事务完成之前执行。这确保了事务读取最新的值,只影响事务的延迟。这种一致性级别还包括BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。
-
AFTER
RW事务等待其更改被应用到所有其他成员上。这对RO事务没有影响。当事务在本地成员上提交时,这种模式确保了在任何组成员上读取最新的值或更晚的值。使用这种模式可以确保读取最新的数据,包括最新的写入。这减少了每个RO事务的同步开销,通过确保只有RW事务使用同步。这种一致性级别还包括BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。
-
BEFORE_AND_AFTER
RW事务等待1)所有前一个事务完成之前应用和2)直到其更改被应用到其他成员上。RO事务等待所有前一个事务完成之前执行。这一致性级别还包括BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。
前 BEFORE
和 BEFORE_AND_AFTER
一致性级别都可以在 RO 和 RW 事务中使用。 AFTER
一致性级别对 RO 事务没有影响,因为它们不生成更改。
不同的 一致性级别为 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
。 -
场景 7 在场景 6 中的同一个系统上,每天有一条指令需要执行一些分析处理,因此需要总是读取最新的数据。为实现这一点,您只需要在该指令上
SET @@SESSION.group_replication_consistency= ‘BEFORE’
。
总之,您不需要在所有事务中使用特定的一致性级别,特别是如果只有某些事务实际需要它。
请注意,在 Group Replication 中,所有读写事务都是完全有序的,因此即使您将当前会话的一致性级别设置为 AFTER
,该事务仍将等待直到所有成员上应用了更改,这意味着等待包括该事务在内的所有先前的事务。
另一种分类一致性级别的方式是根据它们对组的影响,也就是说,一致性级别对其他成员的影响。
前一致性级别,除了按照事务流排序外,还仅影响本地成员。这意味着,它不需要与其他成员协调,也不会对他们的事务产生影响。换言之,BEFORE
仅影响使用它的事务。
然而,AFTER
和BEFORE_AND_AFTER
一致性级别确实会对并发事务产生影响,这些事务在其他成员上执行。如果事务具有EVENTUAL
一致性级别,并且在AFTER
或BEFORE_AND_AFTER
事务执行时启动,那么其他成员的事务将等待,直到AFTER
事务在该成员上提交,即使其他成员的事务具有EVENTUAL
一致性级别。换言之,AFTER
和BEFORE_AND_AFTER
影响所有ONLINE
组成员。
为了进一步说明,想象一个由三个成员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
成员上使用一致性级别BEFORE
、AFTER
和BEFORE_AND_AFTER
,尝试在其他状态的成员上使用它们将导致会话错误。
其一致性级别不是EVENTUAL
的事务将等待,直到超时,配置的wait_timeout
值达到,默认为8小时。如果超时达到,将抛出ER_GR_HOLD_WAIT_TIMEOUT
错误。
本节描述了组的一致性级别如何影响单主组的主选举。该组自动检测故障并调整活动成员的视图,即成员配置。此外,如果组在单主模式下部署,每当组成员关系发生变化时,都会检查是否仍有主成员在组中。如果没有,新的主成员将从次要成员列表中选出。通常,这被称为次要成员升级。
鉴于系统可以自动检测故障并重新配置自己,用户也可能期望,一旦升级完成,新的主成员将与旧的主成员处于相同的数据状态。换言之,用户可能期望,一旦应用程序故障转移到新的主成员上,就不会读取旧数据或写入旧数据记录。
当流控制激活并正确调整组时,只有很小的机会在新的主成员上读取过时的数据,或者在升级后写入旧数据记录。此外,您可能拥有代理或中间件层来控制应用程序对新的主成员的访问,并在该层级上实施一致性标准。如果您的组成员使用MySQL 8.0.14或更高版本,您可以使用group_replication_consistency
变量来控制新的主成员的行为,一旦升级完成,是否阻止读取和写入,直到所有待处理的事务都被应用完毕。
-
没有过时的读取结果对于只读和读写事务。这防止了新的主成员将过时的读取结果外部化到应用程序中。
-
没有虚拟回滚对于读写事务,原因是写写冲突与待处理的读写事务。
-
没有读取偏移对于读写事务,例如:
> 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
时,您选择了优先考虑一致性,而不是可用性,因为读取和写入都会在新primary被选举时被hold。这是您在配置组时需要考虑的权衡。此外,如果流控制正确,backlog应该是最小的。请注意,高一致性级别BEFORE
、AFTER
和BEFORE_AND_AFTER
也包括BEFORE_ON_PRIMARY_FAILOVER
提供的一致性保证。
为了确保组提供相同的一致性级别,不管哪个成员被提升为primary,所有组成员都应该将BEFORE_ON_PRIMARY_FAILOVER
(或更高的一致性级别)持久化到其配置中。例如,在每个成员上执行:
> SET PERSIST group_replication_consistency='BEFORE_ON_PRIMARY_FAILOVER';
这确保了成员都以相同的方式行为,并且配置在成员重启后被持久化。
事务不能被无限期hold,如果hold的时间超过wait_timeout
,它将返回一个ER_GR_HOLD_WAIT_TIMEOUT错误。
尽管使用BEFORE_ON_PRIMARY_FAILOVER
一致性级别时所有写入都会被hold,但不是所有读取都会被阻止,以便您可以在服务器应用backlog后仍然可以inspect服务器。这对于调试、监控、可观察性和故障排除非常有用。一些不修改数据的查询被允许,例如:
允许的SHOW
语句是SHOW VARIABLES
、SHOW PROCESSLIST
、SHOW STATUS
、SHOW ENGINE INNODB LOGS
、SHOW ENGINE INNODB STATUS
、SHOW ENGINE INNODB MUTEX
、SHOW BINARY LOG 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
。