虽然事务同步点一节从概念上解释了您可以从两个同步点中进行选择:读取时或写入时,但这些术语是一种简化,组复制中使用的术语是:事务执行之前和事务执行之后。一致性级别对组处理的只读 (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
提供的一致性保证。
BEFORE
和BEFORE_AND_AFTER
一致性级别都可用于 RO 和 RW 事务。 AFTER
一致性级别对 RO 事务没有影响,因为它们不会生成更改。
不同的 consistency 级别为 DBA 和开发人员都提供了灵活性,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’
。
总而言之,您不需要以特定的一致性级别运行所有事务,尤其是在只有某些事务实际需要它时。
请注意,所有读写事务在组复制中都是完全有序的,因此即使您为当前会话设置了一致性级别 AFTER
,此事务也会等到其更改应用于所有成员后才会继续,这意味着要等待此事务以及所有可能位于辅助服务器队列中的先前事务。实际上,一致性级别 AFTER
会一直等到此事务(包括此事务)完成。
对一致性级别进行分类的另一种方法是根据对组的影响,即一致性级别对其他成员产生的影响。
BEFORE
一致性级别除了在事务流中排序外,仅影响本地成员。也就是说,它不需要与其他成员协调,也不会对其他成员的事务产生影响。换句话说,BEFORE
仅影响使用它的事务。
AFTER
和 BEFORE_AND_AFTER
一致性级别确实会对在其他成员上执行的并发事务产生副作用。如果在执行一致性级别为 AFTER
或 BEFORE_AND_AFTER
的事务时启动了一致性级别为 EVENTUAL
的事务,则这些一致性级别将使其他成员的事务等待。其他成员会一直等到 AFTER
事务在该成员上提交,即使其他成员的事务具有一致性级别 EVENTUAL
。换句话说,AFTER
和 BEFORE_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 上处于提交阶段时开始执行的,因此第二个事务必须等待第一个事务完成提交后才能执行。
您只能在 ONLINE
成员上使用一致性级别 BEFORE
、AFTER
和 BEFORE_AND_AFTER
,尝试在处于其他状态的成员上使用它们会导致会话错误。
一致性级别不是 EVENTUAL
的事务将一直暂停执行,直到达到由 wait_timeout
值配置的超时时间(默认为 8 小时)。如果达到超时时间,则会抛出 ER_GR_HOLD_WAIT_TIMEOUT
错误。
本节介绍组的一致性级别如何影响已选出新主服务器的单主服务器组。此类组会自动检测故障并调整活动成员的视图,换句话说,就是成员资格配置。此外,如果组以单主服务器模式部署,则每当组的成员资格发生更改时,都会执行检查以检测组中是否还有主服务器成员。如果没有,则从辅助服务器成员列表中选择一个新的主服务器成员。通常,这称为辅助服务器提升。
鉴于系统会自动检测故障并重新配置自身,用户可能还希望一旦完成提升,新主服务器在数据方面就与旧主服务器处于完全相同的状态。换句话说,用户可能希望一旦他的应用程序故障转移到新主服务器,即使是暂时地,也不会有机会读取旧数据或写入旧数据记录。
当在组上激活并正确调整了流量控制时,只有很小的几率会在提升后立即从新选举的主服务器读取过时的数据,因为不应该有积压,或者如果有积压,积压应该很小。此外,您可能拥有代理或中间件层,用于管理在提升后应用程序对主服务器的访问,并在该级别强制执行一致性标准。您可以使用 group_replication_consistency
变量指定新主服务器在提升后的行为,该变量控制新选举的主服务器是在完全应用积压后才阻止读取和写入。如果在有积压需要应用的新选举的主服务器上将 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
、AFTER
和 BEFORE_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
语句包括 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
。