本节介绍如何使用可用的系统变量对组复制进行性能优化,以便获得最佳性能。


6.1. 微调组通信线程


当加载并启动MGR插件时,组通信线程(GCT)就会不断循环运行。GCT接收来自组和MGR插件的消息,处理与仲裁和故障检测相关的任务,发送一些保活的通讯消息,还处理MySQL Server与组之间传入和传出的事务。GCT会等待队列中的传入消息。当队列中没有消息时,GCT将会进行等待。在某些情况下,通过将这个等待配置得稍微长一些(进行主动等待),可以减少操作系统执行上下文切换时从处理器中换出GCT线程的次数。


要强制GCT执行主动等待,请使用系统变量group_replication_poll_spin_loops进行设置,这使得 GCT 在对下一个消息进行实际轮询队列之前,在已配置的循环次数内进行循环时不做任何相关操作(该系统变量设置的值表示需要等待通信引擎互斥锁(mutex)被释放的次数,不是时间单位)。


mysql> SET GLOBAL group_replication_poll_spin_loops= 10000;


6.2. 流量控制


组复制可确保事务仅在组中的大多数成员接收到它,且并发发送的所有事务在所有接收到事务的成员之间的相对顺序达成一致后,就可以执行事务的提交操作。如果对组的写入并发事务总数不超过组中任何成员的写入容量(提供写服务的能力),则此方法可以获得很好的性能。但如果组中所有成员能够提供的最大写服务能力不相同,那么组中服务能力低的成员可能出现数据延迟(例如:一些成员能提供3000TPS的写能力,但是有一些成员只能提供2000TPS的写能力),那么,当对能够提供3000TPS的成员写入并发3000的事务时,只能提供2000TPS的成员就会出现延迟(数据落后于能够提供3000TPS的成员)。


组中如果有成员出现数据延迟,将有可能导致应用程序对这些成员执行读操作时,读取到非常陈旧的数据,另外,组中的其他不存在数据延迟的成员或多或少需要保存一些复制上下文(binlog日志记录),以满足来自存在数据延迟的慢速成员潜在的数据传输请求。但是,复制协议中有一种机制可以避免在快成员和慢成员之间存在过大的事务差距。这就是所谓的流量控制机制。流量控制机制图解决如下几个问题:


* 保持成员之间的数据足够接近(慢速成员没有太大数据延迟)。

* 快速适应组中不断变化的环境。如,适应不同的工作负载或更多写操作。

* 让组中的每个成员能够提供的写服务能力得到一个平衡。

* 在非严格必要的情况下,不降低吞吐量,以避免浪费资源。


考虑到组复制的设计,在决定是否需要启用流量控制时,可能要考虑两个工作队列:认证队列和二进制日志应用队列。当其中一个队列的大小超过用户定义的阈值时,就会触发流量控制机制。对于流量控制配置:首先,需要选择对谁配置流量控制,是对认证队列、还是针对应用队列、还是两者都需要配置流量控制。然后,对需要配置流量控制的对象(认证队列和应用队列)设置流量控制阈值。


流量控制依赖于两个基本机制:

* 对组成员进行监控,并收集所有组成员的吞吐量和队列大小的一些统计信息,从而对每个组成员能够承受的最大写压力进行有根据的猜测(评估);

* 对组中的所有成员的并发写能力时刻保持监控,一旦某成员的并发压力超过了组中所有成员的平均写能力,就会对其执行流量控制。


6.2.1. 探测和统计


监控机制通过在每个成员上部署一组探测器来收集关于其工作队列和吞吐量的信息。然后,将收集到的信息定期发送给组,以便与其他成员共享这些探测数据。


这些探测器被分散在MGR插件的堆栈中,允许它们建立相应的度量指标,如下(这些指标值在performance_schema.replication_group_member_stats表中能够查询到):


* 认证队列大小

* 复制应用队列大小

* 认证完成的事务总数

* 组成员中应用的远程事务的总数

* 本地事务的总数


一旦一个成员收到来自另一个成员的带有统计信息的消息,它就会计算关于在最后一个监控探测期间,认证、应用和本地执行的事务数量等相关的度量指标。


监控数据定期与组内其他成员共享。监控周期(频率)必须足够高,以便其他成员能够根据这些监控信息来确定当前的写请求量,但也必须足够低,以便对组带宽的影响最小。监控信息每秒钟都会被共享,一秒的时间间隔通常情况下能够解决这两个问题且能够很好地在这两个问题之间取得一个平衡。


6.2.2. 组复制节流


组复制节流,指的是基于从组中所有成员中收集的度量指标,来决定是否启用限制成员"执行/提交"新事务的速度的一种节流机制。因此,从所有组成员获取的度量指标是计算每个组成员容量的基础:如果一个成员有一个大的队列(用于认证或复制应用线程),那么执行新事务的能力应该接近于上一阶段(最后一次探测时间段)认证或复制应用事务的能力。


组中所有成员的最低容量(写能力)决定了组的实际容量,而本地事务的数量决定了有多少成员向其写入数据,因此也决定了应该与多少成员共享可用的容量。这意味着每个成员都有一个基于可用容量的写限额,换句话说,它就是下一个时间段内可以安全(不受节流机制影响)地执行的事务数量。如果认证队列或二进制日志应用队列大小超过用户定义的阈值,则将通过节流机制强制执行写限额。


限额将根据上一阶段延迟的事务数量逐步减少10%,以让触发节流机制的队列大小减少到触发阈值以内。待到恢复后,为避免在队列大小超过阈值时出现吞吐量的陡增,在此之后,每个时间段的吞吐量只允许增长相同的10%。


当前的节流机制不会对限额内的事务造成影响,但是会延迟完成那些超过限额的事务,直到监控周期结束。因此,如果写限额设置的非常小,一些事务的延迟可能会接近一个监控周期。


6.3. 消息压缩


当网络带宽成为瓶颈时,消息压缩可以在组通信级别上将吞吐量提高达30-40%。这对于负载较大的大型组尤其重要。下表列出了在不同的二进制日志格式下的LZ4压缩率。


工作负载模拟程序 行格式压缩比例 语句格式压缩比例

mysqlslapd

4,5 4,1

sysbench

3,4 2,9


组中N个参与者之间的相互连接的TCP具有对等性质,使得发送方需要发送N次相同数量的数据(例如:组中有3个成员,那么发送方就要发送3次相同的数据)。此外,二进制日志可能具有较高的压缩比(见上表)。这使得压缩对于包含大事务的工作负载来说是一个引人注目的特性。在MGR插件中,支持压缩的是组通讯API组件,如下图 。




MGR 插件架构如上图所示,压缩功能在插件的五层(位于MySQL Server和复制组之间,刨去MySQL Server层,它是MGR插件的第四层,也就是组通讯引擎层)。压缩和解压缩的工作任务由组通信系统API处理。压缩发生在数据被传递给组通信线程之前的组通讯引擎,所以它发生在MySQL 用户会话线程的上下文中。事务有效负载可能在发送到组之前进行压缩,在接收之后进行解压缩。压缩是有条件的,并且依赖于一个配置的阈值。压缩功能默认启用。


此外,并不要求组中的所有成员都启用压缩来协同工作。在收到消息后,成员会检查消息信封以验证它是否已被压缩。如果需要,则该成员在将事务交付给上层组件之前会对其进行解压。


使用的压缩算法是LZ4。默认情况下启用压缩,阈值为1000000字节(1M)。压缩阈值(以字节为单位)可以根据需要设置为比默认值更大的值。当压缩阈值不为0时,只有有效负载大于阈值的事务才会被压缩。设置压缩阈值示例如下:


# 这将压缩阈值设置为2MB。如果事务生成的复制消息的有效负载大于2MB,例如:二进制日志事务条目大于2MB,则对其进行压缩。若要禁用压缩,请将阈值设置为0。
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_compression_threshold= 2097152;
START GROUP_REPLICATION;


6.4. 消息分段


当在组复制组成员之间发送异常大的消息时,可能导致某些组成员发生失败并被驱逐出组。这是因为组复制的组通信引擎(XCom, Paxos变体)使用的单个线程占用的处理消息的时间太长,因此某些组成员可能会报告消息接收失败。默认情况下,从MySQL 8.0.16开始,大的消息被自动分割成片段,分别发送,然后由接收者重新组合这些消息片段。


系统变量group_replication_communication_max_message_size指定组复制通信的最大消息大小,超过该大小的消息将被分段。默认的最大消息大小是10485760字节(10 MiB)。该系统变量的最大允许值与系统变量slave_max_allowed_packet的最大值相同(后者是1073741824字节,即 1GB),系统变量group_replication_communication_max_message_size的设置值必须小于系统变量slave_max_allowed_packet的设置值,因为应用线程不能处理大于系统变量slave_max_allowed_packet的消息片段。要关闭消息分段功能,请将系统变量group_replication_communication_max_message_size设置为零值。


与大多数其他组复制系统变量一样,修改系统变量group_replication_communication_max_message_size必须重新启动组复制才能使更改生效。例如:


STOP GROUP_REPLICATION;
SET GLOBAL group_replication_communication_max_message_size= 5242880;
START GROUP_REPLICATION;


当所有组成员都接收并重新组合了消息的所有片段时,就认为分段消息的消息传递已经完成了。分段消息的头部包含了一些信息,这些信息使成员能够在消息传输期间加入组,并恢复加入组之前发送的早期消息片段。如果joiner节点无法恢复消息片段,则会将自己从组中驱逐出去。


为了让一个复制组正常使用消息分段功能,所有组成员必须运行MySQL 8.0.16或以上版本,并且组使用的组复制通信协议版本必须支持消息分段。可以使用group_replication_get_communication_protocol() UDF检查组使用的通信协议版本是多少,UDF 返回版本号字符串代表了组支持的最老的MySQL Server版本。MySQL 5.7.14的版本支持压缩消息,MySQL 8.0.16的版本支持消息分段。如果所有组成员都运行在MySQL 8.0.16以上版本,并且组中不需要运行更低版本的组成员,则可以使用group_replication_set_communication_protocol UDF()来设置通信协议版本为MySQL 8.0.16及其以上,这样就能够确保消息分段功能在组中所有成员上正常运行。有关更多信息,请参见"4.1.4. 设置组的通信协议版本”。


如果复制组由于某些成员不支持消息分段导致组不能使用消息分段,则可以使用系统变量group_replication_transaction_size_limit来限制该组所接受的最大事务大小。在MySQL 8.0中,默认设置大约为143 MB。超过这个大小的事务将被回滚。还可以使用系统变量group_replication_member_expel_timeout来设置一个在成员被驱逐出组之前,它被怀疑失败的额外时间(默认为0,从8.0.14版本开始,最大值为一个小时)。即,在该系统变量设置的时间内,被怀疑的成员不会被驱逐出组。


6.5. XCom 缓存管理


用于组复制的组通信引擎(XCom, Paxos变体)包含了一个消息(及其元数据)缓存,该消息是作为组成员之间交换协商一致性协议的一部分。在其他用途中,消息缓存可用于在一段时间内无法与其他组成员通信的成员在重新返回到组使进行恢复。


从MySQL 8.0.16开始,可以使用系统变量group_replication_message_cache_size为XCom的消息缓存设置缓存大小限制。这个系统变量的默认值和最小值为1 GB,即MySQL Server 8.0.16 版本之前的消息缓存大小设置。如果达到了缓存大小限制设置,XCom将删除已经确定和交付的最老的条目。考虑到MySQL Server的其他缓存和对象池的大小,请确保在系统上有足够的内存来满足所设置的缓存大小限制。


如果一个不可达成员尝试重新恢复连接时,需要一条恢复消息,但该消息已从消息缓存中删除,则该成员无法重新连接。如果使用了系统变量group_replication_member_expel_timeout(该系统变量在MySQL 8.0.13中引入)指定一个额外的延迟时间,则更有可能出现这种情况。当不可达的成员恢复时可能需要使用到的消息在消息缓存中已经被删除时,组复制的组通信系统(GCS)通过一条警告消息来发出警告。此警告消息记录在所有活跃的组成员上(对于每个不可到达的成员仅记录一次)。尽管组成员不能确定不可到达的成员最后看到的消息是什么消息,但是警告消息表明缓存大小可能不足以支撑通过系统变量group_replication_member_expel_timeout设置的在驱逐成员之前的等待时间内总的消息大小。在这种情况下,可以增加缓存大小限制,以便消息缓存能够存放组成员重新加入组所需的所有遗漏消息。


如果考虑减少缓存大小限制,可以使用以下语句先查询performance_schema.memory_summary_global_by_event_name表中记录的相关内存分配情况:


# 查询语句返回消息缓存的内存使用统计信息,包括当前缓存条目的数量和当前缓存的大小。如果降低了缓存大小限制,XCom将删除已经确定并交付的最老的条目,直到当前大小低于限制值为止。在删除最老的条目过程进行期间,XCom可能会暂时超过缓存大小限制。
mysql> SELECT * FROM performance_schema.memory_summary_global_by_event_name
  WHERE EVENT_NAME LIKE "memory/group_rpl/GCS_XCom::xcom_cache";


6.6. 对故障检测和网络分区的响应


组复制的故障检测机制旨在识别不能与组正常通信的组成员,并在他们可能发生故障时将他们从组中驱逐出去。当组中有成员发生故障时,如果组中存在多数成员存活,则故障检测机制能够使得组正确恢复可用性,以便能够及时恢复并正确处理客户端的请求。


通常,所有组成员会定期与所有其他组成员交换消息。如果一个组成员在5秒内没有收到来自某个特定成员的任何消息,当这个检测周期结束时,就会产生对该成员的怀疑。当一个可疑成员超时时(在最大允许的怀疑时间范围内仍然没有任何消息),该可疑成员就被认定为失败了,并被驱逐出组。被驱逐的成员会被组中所有活跃成员从组成员资格列表中删除,但被驱逐的成员自己可能不知道已经被驱逐出组(例如:它自己还在线,只是无法联系其他成员)。如果被驱逐的成员实际上没有失败(例如,因为临时网络问题而断开连接),并且后续能够恢复与其他成员的正常通信,则在网络恢复之后它会收到一个包含了该成员已被驱逐出该组的新视图信息。


组成员(包括失败的成员本身)对这些情况的响应可以在流程中的许多地方进行配置。默认情况下,如果怀疑某个成员失败,则会发生以下行为:


* 当创建怀疑对象时,它将立即超时(其生存期设置为0),因此一旦怀疑对象发生超时,嫌疑成员就会被驱逐。成员可能在超时后继续存活几秒钟,因为对怀疑对象的检查是周期性的。

* 如果被驱逐的成员恢复了正常通讯,并意识到自己被驱逐了,它就不会试图重新加入到该组,而会接受驱逐结果。

* 当一个被驱逐的成员接受它的驱逐结果时,它就会切换到超级只读模式(设置super_read_only=1。注意:设置super_read_only=ON时,read_only会自动设置为ON,但在将super_read_only=OFF时,不会自动将read_only设置为OFF),直到人工介入处理(注意:在MySQL 8.0.12到8.0.15的版本中,组成员被驱逐时默认的行为是关闭自身数据库进程。从MySQL 8.0.16开始,默认行为被更改为匹配MySQL 5.7中的行为,即,设置超级只读模式)。


设置这些默认值是为了优先考虑组的正确操作和对请求的正确处理。但是,在较慢的网络或瞬时故障率较高的网络中,这些默认值可能会带来不便,因为在这些情况下,经常需要人工介入修复被驱逐的成员。它们也不允许在预期的网络故障或Server速度变慢的情况下对组计划执行一些操作。但,为了满足系统的一些优先级处理需求,可以使用本节中介绍的一些组复制配置系统变量来修改这些默认行为。


活跃成员可能由于网络分区而与复制组的一部分(不是全部)失去联系。例如,在一个由5个成员组成的组(S1、S2、S3、S4、S5)中,如果(S1、S2)和(S3、S4、S5)之间断开连接,则这就表示存在一个网络分区。第一组(S1,S2)成为了少数成员的一部分,因为它并不拥有多数成员(不超过总成员数的一半),这时,少数成员的组部分处理的任何事务都将被阻塞,因为它们无法访问该组的大多数成员,因此该组部分无法执行仲裁。有关此场景的详细描述,请参见"4.4. 网络分区”。在这种情况下,默认的行为是少数成员部分和多数成员部分都能够继续接受事务(尽管在少数成员的组部分的请求会被阻塞,但是,请求并不会被拒绝),此时,必须人工介入处理。但此默认行为是可配置的。


请注意,如果组成员运行在不支持相关设置的旧MySQL Server版本下,或者具有不同的默认设置的版本中,那么他们将根据上述默认行为对自己和其他组成员采取行动。例如,不支持系统变量group_replication_member_expel_timeout的组成员将在检测到怀疑对象超时时立即驱逐其他成员,并且驱逐结果将被其他成员接受,即使其他成员支持该系统变量并设置了更长的超时时间也不影响该驱逐结果。


6.6.1. 超时驱逐


可以使用系统变量group_replication_member_expel_timeout(该变量在MySQL 8.0.13中引入)来设置在创建可疑成员和驱逐可疑成员之间允许的超时时间(也可以看做是驱逐等待期或者生存期)。


当组中的其他成员对它的怀疑(或它对自己的怀疑)超时时,该组成员将被驱逐出组。默认情况下,系统变量group_replication_member_expel_timeout设置为0,表示没有等待期,在5秒的检测周期结束后,可疑成员可能立即被驱逐出组。在驱逐机制检测到并实施驱逐之前,可能需要一段较短的时间。如果一个组成员使用的是不支持此系统变量设置的旧MySQL Server版本,那么其行为就类似于系统变量group_replication_member_expel_timeout设置为0。


为了避免在较慢的网络上发生不必要的驱逐,或者在可预期的瞬时网络故障或服务器突然变慢的情况下,您可以指定一个大于零的超时值,最长3600秒(1小时)。此状态下的可疑成员被列为不可访问,但不会从组的成员资格列表中删除。如果可疑成员在怀疑超时之前再次变为活跃状态,它将重新加入该组,并应用组中其他成员的中缓存的所有消息,应用完成之后就会进入在线状态。


如果超过了怀疑超时时间,可疑成员将在怀疑超时后立即被驱逐出组。如果该成员后续能够恢复通信并接收到被驱逐的视图,它会发现自己已经被驱逐了,并接受驱逐结果。默认情况下,此时被驱逐的成员会遵循系统变量group_replication_exit_state_action指定的退出操作。或者,可以使用系统变量group_replication_autorejoin_tries(MySQL 8.0.16中引入)使成员自动尝试重新加入组。


在驱逐一个成员之前的等待期只适用于先前在该组中活跃的成员。在组中从未成为活跃成员的Server并没有这个等待期待遇,如果在检测周期内发现了,就会被立即从成员资格列表中删除,因为他们花费了太长时间来加入组,且加入组还失败了。


如果组中的任何成员受到怀疑,则就无法重新配置该组成员的身份(通过添加或删除成员或选举新主要节点)。如果在一个或多个组成员受到怀疑时需要执行组成员资格变更,并且希望可疑成员继续留在组中,那么可以采取任何可行的方法来使成员再次变为活跃状态(如果可能的话)。如果不能让组成员再次变为活跃状态且希望将其驱逐出组,则可以强制被怀疑的组成员立即超时。通过将系统变量group_replication_member_expel_timeout的值更改为一个比怀疑时间更短的值即可,这样,可疑成员就会立即被驱逐出组。


有关在系统变量group_replication_member_expel_timeout不可用时,如何避免不必要的驱逐,详情请参阅"9.2.  组复制限制”。


6.6.2. 与多数成员失联超时


默认情况下,由于网络分区而处于少数成员的组部分不会自动脱离组。可以使用系统变量group_replication_unreachable_majority_timeout设置一个成员在与大多数组成员失去联系后等待的秒数,超过这个设置时间之后,就会自动退出组。设置失联超时意味着不需要在发生网络分区之后主动监控少数组成员的组部分(它们会自行退出组),这样可以避免由于不适当的人为干预造成脑裂(具有两个不同组视图版本的组成员资格)的情况。


当系统变量group_replication_unreachable_majority_timeout指定的失联超时过期时,由该成员和该成员所处的少数成员的组部分中的其他所有成员正在处理的所有挂起事务都将被回滚,该组部分中的成员状态将变更为ERROR状态。默认情况下,少数派成员随后将执行系统变量group_replication_exit_state_action指定的退出操作。或者,可以使用系统变量group_replication_autorejoin_tries(MySQL 8.0.16中引入)使成员自动尝试重新加入组。


在决定是否设置与多数成员失联超时的系统变量时,需要考虑以下几点:


* 在一个对称的组中,例如有两个或四个成员的组,如果两个网络分区都包含了相同数量的成员,则两个组部分都会认为自己属于少数派,并都会进入ERROR状态。在这种情况下,组没有任何一个网络分区可用(即,没有任何一个被网络拆分的组部分可用正常对外提供服务)。

* 当存在少数派的组部分时,少数派组部分处理的任何事务都将被接受(不会被拒绝),但会被阻塞,因为少数派组部分的成员无法达到法定人数(即,不满足达成共识所需的多数成员要求),直到在这些成员上执行STOP GROUP_REPLICATION语句,或处于这种状态达到超时之后自动处理脱离组操作为止。

* 如果没有设置与多数成员失联超时,则少数派组部分中的成员将永远不会自动进入ERROR状态,此时,你必须手动停止它们。

* 如果在检测到与多数成员失联超时之后,再到少数派成员上设置与多数成员失联超时的设置,则此时设置无效,需要提前设置才会生效。


如果不使用系统变量group_replication_unreachable_majority_timeout,则在发生网络分区时,人工处理过程详见"4.4 网络分区”。


6.6.3. 自动重新加入组


系统变量group_replication_autorejoin_tries是在MySQL 8.0.16引入的,它可以使一个被驱逐出组的成员(此时,被驱逐的成员还未接受驱逐结果)或与多数成员失联超时的成员自动重新加入组。可以使用该系统变量来指定该成员重新加入组的尝试次数,让其自动重新加入组,而不是在其恢复与组的通信后立即接受驱逐结果。如果能够容忍读取陈旧数据且希望尽量减少手动干预,特别是在瞬时网络问题频发导致成员被驱逐的情况下,可以考虑启用自动重新加入组的功能。


当成员被驱逐或者与多数成员失联超时,如果系统变量group_replication_autorejoin_tries设置了一个非0值,则它将自动尝试重新加入组,直到耗尽指定的尝试次数为止。在一次尝试自动重新加入组失败之后,会等待5分钟之后再次尝试重新加入组。如果重试次数被耗尽之后,该成员仍然没有成功加入组或者未被执行停止MGR插件的操作,则该成员将继续执行系统变量group_replication_exit_state_action指定的退出操作。如果系统变量group_replication_autorejoin_tries设置为0值,则等待系统变量group_replication_unreachable_majority_timeout设置的超时时间之后,直接执行系统变量group_replication_exit_state_action指定的退出操作。


在自动重新加入组的过程中,被驱逐的成员保持在超级只读模式,并在其复制组视图上显示为ERROR状态。但要注意,虽然成员处于超级只读模式,不能对成员执行写操作,但是可以执行读操作,并且随着时间的推移,读取到陈旧数据的可能性会越来越大(因为此时并不能同步组中的最新数据)。如果此时希望成员脱离组,则可以随时使用STOP GROUP_REPLICATION语句或关闭数据库Server进程来手动关闭该成员。


可以使用performance_schema下的表来监控自动重新加入组的过程。当执行自动重新加入组时,performance_schema.events_stages_current表中会记录“Undergoing auto-rejoin procedure”的事件,以及到目前为止(查询该表的时间点)该事件执行的次数(在WORK_COMPLETED字段中)。performance_schema.events_stages_summary_global_by_event_name表中记录了Server自动重新加入组的过程的次数(在COUNT_STAR字段中)。performance_schema.events_stages_history_long表中记录了每次自动重新加入组的过程完成时间(在TIMER_END字段中)。


6.6.4. 退出操作


系统变量group_replication_exit_state_action在MySQL 8.0.12及其之后的版本、MySQL 5.7.24及其之后的版本中引入,它指定当组成员由于发生错误或未知问题而意外脱离组、或者无法自动重新加入组、或者尝试自动加入组次数耗尽时,组复制会执行什么操作(这里指的是组成员退出组时需要做的操作)。请注意,对于被驱逐出组的成员,在其重新加入到组之前,该成员并不知道自己已被驱逐出组,因此,只有当该成员设法重新与组建立连接、或该成员对自己产生怀疑并将自己驱逐出组时,才会采取指定的操作(即,系统变量group_replication_exit_state_action指定的操作)。


关于退出操作,按影响顺序依次如下:


* 如果退出操作配置为READ_ONLY,则会通过将系统变量super_read_only设置为ON,以便将MySQL切换到超级只读模式。当成员处于超级只读模式时,客户端不能执行任何更新操作,即使他们拥有super权限。但是,客户端仍然可以读取数据,由于数据不再更新,所以,随着时间的推移,读取到陈旧的数据的概率会大大增加。因此,使用此设置时,需要主动监控Server的故障状态。该退出操作也是MySQL 8.0.16及其之后版本的默认操作。执行此退出操作后,成员的状态将在组视图中显示为ERROR状态。


* 如果退出操作配置为OFFLINE_MODE,则会通过将系统变量offline_mode设置为ON,以便将MySQL切换到离线模式。当成员处于离线模式时,连接的客户端用户执行下一个请求时连接会被断开,且不再接受其新的连接请求,只接受具有CONNECTION_ADMIN或super权限的用户建立新的客户端连接。组复制还会将系统变量super_read_only设置为ON,以阻止普通用户与超级用户执行更新操作。此退出操作可以防止更新操作,也可以防止读取到陈旧的数据(因为普通用户无法再次建立连接,但具有指定权限的客户端用户如果要在这个时候执行查询,则仍然可能读取到陈旧的数据)。同时允许MySQL Server继续运行,以便管理员可以尝试解决问题而不关闭MySQL Server进程。此退出操作在MySQL 8.0.18中可用。在执行此退出操作之后,成员的状态将在组视图中显示为ERROR状态(不是OFFLINE,这意味着MGR插件可用,但该成员当前它不属于组)。


* 如果退出操作配置为ABORT_SERVER,则MySQL Server将被关闭。虽然这可以防止所有的更新操作和读取陈旧的数据,但也意味着MySQL Server不可用,必须重新启动Server进程。该退出操作在MySQL 8.0.12版本中引入,且在大于等于8.0.12与小于等于8.0.15之间的版本中为默认的退出操作。执行此退出操作后,退出成员将被从组视图列表中删除。


注意:


* 无论设置什么退出操作,当执行完退出操作之后,都需要人为介入对其进行恢复,此时,不人为执行重启组复制的情况下不允许(也无法)重新加入组。


* 如果Server在成功加入组之前发生失败(从未成功加入组的Server),则不会执行group_replication_exit_state_action系统变量指定的退出操作。例如,在本地配置检查期间出现故障、或者joiner节点的配置与组的配置不匹配,就会出现这种情况。在这些情况下,系统变量super_read_only将保持原始值(不会进行调整),MySQL Server也不会执行关闭动作(当然,此时由于该Server未成功加入组,所以也就无法接受组中的更新数据,此时如果在该Server中发生新的数据写入,将导致后续难以将这些新数据同步到组中)。所以,为了避免这种情况的发生,建议在启动时在配置文件中设置系统变量super_read_only=ON,当配置好组复制之后,会自动将系统变量super_read_only设置为OFF。


如果Server在成功加入组之后发生失败,则会执行如下退出操作。下面是一些导致成员失败的一些场景:


* 应用线程错误:复制应用线程中存在错误。此问题不可自动恢复。


* 无法执行分布式恢复:这意味着无法完成组复制的分布式恢复过程(即,无法使用基于远程克隆操作和基于二进制日志的状态传输)。组复制在这种情况下会自动重试分布式恢复,但如果没有其他更多选择来完成该过程,则组复制将停止。具体参见"4.3.3. 分布式恢复的容错能力"。


* 组配置变更时发生错误:在使用UDF进行组范围的配置变更期间发生错误,详见"4.1. 在线配置组"。


* 选主期间发生错误:在以单主模式运行的组中,执行选主时发生错误,详见"1.3.1. 单主模式"。


* 与多数成员失联超时:该成员已与大多数组成员失去联系,因此它属于少数成员的组部分,且系统变量group_replication_unreachable_majority_timeout设置的超时时间已过期(与多数成员失联时间已超过该系统变量设置的时间)。


* 被驱逐出组的成员:组中的其他成员对该成员产生了怀疑,且系统变量group_replication_member_expel_timeout设置的超时已过期(怀疑期超时时间),当该成员恢复与组的通信之后会发现自己已被驱逐出组。


* 尝试自动重新加入组的次数耗尽:当某个成员与组中的其他大多数成员失联或被驱逐出组之后,会根据系统变量group_replication_autorejoin_tries设置的次数不断尝试自动重新加入组,当该成员耗尽了尝试次数,也仍然能未能成功加入组。


下表总结了组复制的每种故障场景及其对应的退出操作:


失败的场景失败的场景 使用START GROUP_REPLICATION语句启动组复制
启用系统变量group_replication_start_on_boot =ON使组复制随数据库进程一并启动
  • 成员本地配置检查失败

  • 加入组的成员与组配置不匹配

  • 系统变量super_read_only和offline_mode值保持不变

  • 允许MySQL Server继续运行

  • 在启动时设置系统变量super_read_only=ON以防止更新

同左
  • 成员上的应用线程错误

  • 分布式恢复不可用

  • 组配置进行了错误的修改

  • 选主出错

  • 多数成员不可达超时

  • 被驱逐出组的成员

  • 超过自动重新加入组尝试次数仍未成功加入组的成员

  • 系统变量super_read_only设置为ON 

  • 系统变量offline_mode和super_read_only设置为ON 

  • MySQL Server关闭

同左





沃趣科技,让客户用上更好的数据库技术!