MySQL8-中文参考-三十六-

MySQL8 中文参考(三十六)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-repair-table.html

19.5.1.25 复制和修复表

当在一个损坏或其他受损的表上使用REPAIR TABLE语句时,可能会删除无法恢复的行。然而,此语句执行的任何表数据修改都不会被复制,这可能导致源和副本失去同步。因此,在源上的表损坏并使用REPAIR TABLE修复之前,应该先停止复制(如果仍在运行),然后比较源和副本的表副本,并准备好在重新启动复制之前手动纠正任何差异。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-reserved-words.html

19.5.1.26 复制和保留字

当您尝试从旧源复制到新副本并且在源上使用在新 MySQL 版本(在副本上运行)中被视为保留字的标识符时,可能会遇到问题。例如,在 MySQL 5.7 源上命名为 rank 的表列在复制到 MySQL 8.0 副本时可能会导致问题,因为 RANK 是 MySQL 8.0 中的保留字。

在这种情况下,即使从复制中排除使用保留字命名的数据库或表,或者具有使用保留字命名的列的表,复制也可能失败,并显示错误 1064“您的 SQL 语法有误...”。这是因为每个 SQL 事件在执行之前必须由副本解析,以便副本知道哪些数据库对象将受到影响。仅在事件解析后,副本才能应用由--replicate-do-db--replicate-do-table--replicate-ignore-db--replicate-ignore-table定义的任何过滤规则。

要解决源数据库、表或列名称在副本中被视为保留字的问题,请执行以下操作之一:

  • 在源数据库上使用一个或多个ALTER TABLE语句来更改任何数据库对象的名称,其中这些名称在副本中被视为保留字,并将使用旧名称的任何 SQL 语句更改为使用新名称。

  • 在使用这些数据库对象名称的任何 SQL 语句中,将名称写为带有反引号字符(```)的引用标识符。

有关 MySQL 版本的保留字列表,请参阅MySQL Server Version Reference中的 MySQL 8.0 中的关键字和保留字,有关标识符引用规则,请参阅第 11.2 节,“模式对象名称”。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-row-searches.html

19.5.1.27 复制和行搜索

当使用基于行的复制格式的副本应用UPDATEDELETE操作时,必须搜索相关表以查找匹配的行。执行此过程的算法首选使用表的一个索引进行搜索,如果没有合适的索引,则使用哈希表。

算法首先评估表定义中的可用索引,看是否有适合的索引可用,并且如果有多个可能性,哪个索引最适合该操作。算法忽略以下类型的索引:

  • 全文索引。

  • 隐藏索引。

  • 生成的索引。

  • 多值索引。

  • 任何索引,其中行事件的前图像不包含索引的所有列。

如果在排除这些索引类型后没有合适的索引,则算法不使用索引进行搜索。如果有合适的索引,则从候选索引中选择一个索引,按以下优先顺序选择:

  1. 主键。

  2. 具有 NOT NULL 属性的索引,其中索引中的每一列都具有 NOT NULL 属性。如果有多个这样的索引可用,则算法选择这些索引中最左边的索引。

  3. 任何其他索引。如果有多个这样的索引可用,则算法选择这些索引中最左边的索引。

如果算法能够选择主键或唯一索引,其中索引中的每一列都具有NOT NULL属性,则使用该索引来迭代UPDATEDELETE操作中的行。对于行事件中的每一行,算法在索引中查找行以定位要更新的表记录。如果找不到匹配记录,则返回错误 ER_KEY_NOT_FOUND 并停止复制应用程序线程。

如果算法无法找到合适的索引,或者只能找到一个非唯一或包含空值的索引,那么将使用哈希表来帮助识别表记录。算法创建一个哈希表,其中包含UPDATEDELETE操作中的行,键为行的完整前图像。然后,算法遍历目标表中的所有记录,如果找到索引则使用该索引,否则执行全表扫描。对于目标表中的每条记录,它确定该行是否存在于哈希表中。如果在哈希表中找到该行,则更新目标表中的记录,并从哈希表中删除该行。当检查完目标表中的所有记录后,算法验证哈希表是否为空。如果哈希表中仍有任何未匹配的行,则算法返回错误 ER_KEY_NOT_FOUND 并停止复制应用程序线程。

slave_rows_search_algorithms系统变量以前用于控制如何搜索匹配的行。现在不推荐使用这个系统变量,因为默认设置,即使用索引扫描后跟随哈希扫描的方式,对性能最优且在所有场景下都能正常工作。

译文:dev.mysql.com/doc/refman/8.0/en/replication-features-shutdowns.html

19.5.1.28 复制和源或复制关闭

安全地关闭复制源服务器并稍后重新启动是安全的。当副本失去与源的连接时,副本会立即尝试重新连接,如果失败,则定期重试。默认情况下,每隔 60 秒重试一次。可以使用CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)来更改此值。副本还能够处理网络连接中断。但是,副本只有在从源接收到replica_net_timeoutslave_net_timeout秒内没有数据后才会注意到网络中断。如果您的中断时间很短,您可能希望减少replica_net_timeoutslave_net_timeout的值。参见第 19.4.2 节,“处理副本意外停止”。

源端发生不干净的关闭(例如崩溃)可能导致源的二进制日志的最终位置小于副本最近读取的位置,因为源的二进制日志文件没有被刷新。这可能导致源重新启动时副本无法复制。在源服务器的my.cnf文件中设置sync_binlog=1有助于最小化此问题,因为它会导致源更频繁地刷新其二进制日志。对于使用带有事务的InnoDB的复制设置,为了获得最大可能的耐久性和一致性,还应该设置innodb_flush_log_at_trx_commit=1。使用此设置,InnoDB重做日志缓冲区的内容在每个事务提交时写入日志文件,并且日志文件被刷新到磁盘。请注意,即使使用此设置,事务的耐久性仍然不能得到保证,因为操作系统或磁盘硬件可能告诉mysqld刷新到磁盘的操作已经完成,尽管实际上并没有。

干净地关闭一个副本是安全的,因为它会记录下关闭时的位置。但是,请注意副本没有打开临时表;参见 Section 19.5.1.31,“复制和临时表”。不干净的关闭可能会产生问题,特别是如果在问题发生之前磁盘缓存没有刷新到磁盘上:

  • 对于事务,副本会先提交然后更新relay-log.info。如果在这两个操作之间发生意外退出,中继日志处理会继续进行,超过信息文件所指示的位置,并且在重新启动后,副本会重新执行中继日志中最后一个事务之后的事件。

  • 如果副本更新relay-log.info但是在写入刷新到磁盘之前服务器主机崩溃,就会出现类似的问题。为了最大程度减少这种情况发生的机会,在副本的my.cnf文件中设置sync_relay_log_info=1。将sync_relay_log_info设置为 0 会导致不强制写入磁盘,服务器依赖操作系统不时地刷新文件。

对于这些问题类型,系统的容错性会大大增加,如果你有一个良好的不间断电源供应。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-errors.html

19.5.1.29 复制过程中的副本错误

如果一条语句在源端和副本端产生相同的错误(相同的错误代码),错误会被记录,但复制会继续。

如果一条语句在源端和副本端产生不同的错误,复制 SQL 线程将终止,并且副本会在其错误日志中写入一条消息,等待数据库管理员决定如何处理该错误。这包括一种情况,即一条语句在源端或副本端产生错误,但不是同时在两端都出错。要解决这个问题,需要手动连接到副本并确定问题的原因。SHOW REPLICA STATUS(或在 MySQL 8.0.22 之前,SHOW SLAVE STATUS(或在 MySQL 8.0.22 之前,START SLAVE 选项屏蔽(忽略)一些或所有错误。

对于非事务性存储引擎,如MyISAM,可能会出现仅部分更新表并返回错误代码的语句。例如,在多行插入中有一行违反键约束,或者在更新了部分行后长时间的更新语句被终止。如果这种情况发生在源端,副本期望执行该语句会产生相同的错误代码。如果没有产生相同的错误代码,复制 SQL 线程将如前所述停止。

如果在源表和副本上使用不同存储引擎的表之间进行复制,请记住,同一语句在针对表的一个版本运行时可能会产生不同的错误,但在另一个版本上不会,或者可能会导致一个版本的表出现错误,而另一个版本不会。例如,由于MyISAM忽略外键约束,访问源上的InnoDB表的INSERTUPDATE语句可能会导致外键违反,但在副本上的相同语句执行在MyISAM版本的相同表上不会产生此类错误,导致复制停止。

从 MySQL 8.0.31 开始,复制过滤规则首先应用,然后再进行任何权限或行格式检查,这样可以过滤掉任何未通过验证的事务;对于已被过滤的事务不执行任何检查,因此不会引发错误。这意味着副本只能接受给定用户已被授予访问权限的数据库部分(只要该数据库部分的更新使用基于行的复制格式)。在进行升级或迁移到一个使用入站复制用户无法访问管理表的系统或应用程序时,这可能会有所帮助。另请参阅第 19.2.5 节,“服务器如何评估复制过滤规则”。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-sql-mode.html

19.5.1.30 复制和服务器 SQL 模式

在源数据库和副本数据库上使用不同的服务器 SQL 模式设置可能导致相同的INSERT语句在源数据库和副本数据库上处理方式不同,导致源数据库和副本数据库分歧。为了获得最佳结果,您应该始终在源数据库和副本数据库上使用相同的服务器 SQL 模式。无论您使用基于语句还是基于行的复制,这些建议都适用。

如果您正在复制分区表,并且在源数据库和副本数据库上使用不同的 SQL 模式,可能会导致问题。至少,这可能导致数据在源数据库和副本数据库中的分区分布不同。这也可能导致在源数据库上成功插入分区表的数据,在副本数据库上失败。

更多信息,请参见 Section 7.1.11, “Server SQL Modes”。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-temptables.html

19.5.1.31 复制和临时表

在 MySQL 8.0 中,当binlog_format设置为ROWMIXED时,仅使用临时表的语句不会在源上记录,因此临时表不会被复制。涉及临时表和非临时表混合的语句仅在源上为非临时表的操作记录,临时表的操作不会记录。这意味着在副本发生意外关闭时,副本上永远不会有临时表丢失。有关基于行的复制和临时表的更多信息,请参阅基于行的临时表记录。

binlog_format设置为STATEMENT时,涉及临时表的语句在源上记录并在副本上复制,前提是涉及临时表的语句可以安全地使用基于语句的格式记录。在这种情况下,在副本上丢失复制的临时表可能是一个问题。在基于语句的复制模式中,当服务器上使用 GTIDs 时(即,当enforce_gtid_consistency系统变量设置为ON时),不能在事务、过程、函数或触发器中使用CREATE TEMPORARY TABLEDROP TEMPORARY TABLE语句。当使用 GTIDs 时,可以在这些上下文之外使用它们,前提是设置了autocommit=1

由于基于行或混合复制模式与基于语句的复制模式在临时表行为上的差异,如果更改适用于包含任何打开临时表的上下文(全局或会话),则不能在运行时切换复制格式。有关更多详细信息,请参阅binlog_format选项的描述。

在使用临时表时安全地关闭复制。 在基于语句的复制模式下,临时表会被复制,除非您停止复制服务器(而不仅仅是复制线程),并且您已经复制了在副本上尚未执行的更新中使用的临时表。如果停止复制服务器,则在重新启动副本时,这些更新所需的临时表将不再可用。为了避免这个问题,请不要在副本有打开的临时表时关闭副本。而是使用以下过程:

  1. 发出STOP REPLICA SQL_THREAD语句。

  2. 使用SHOW STATUS来检查Replica_open_temp_tablesSlave_open_temp_tables状态变量的值。

  3. 如果值不为 0,请使用START REPLICA SQL_THREAD重新启动复制 SQL 线程,稍后重复该过程。

  4. 当值为 0 时,发出mysqladmin shutdown命令来停止复制。

临时表和复制选项。 默认情况下,使用基于语句的复制时,所有临时表都会被复制;无论是否存在任何匹配的--replicate-do-db--replicate-do-table,或--replicate-wild-do-table选项。但是,对于临时表,会遵守--replicate-ignore-table--replicate-wild-ignore-table选项。唯一的例外是,为了在会话结束时正确删除临时表,复制总是会复制DROP TEMPORARY TABLE IF EXISTS语句,而不管通常适用于指定表的任何排除规则。

在使用基于语句的复制时,建议指定一个专用前缀用于命名不希望被复制的临时表,然后使用--replicate-wild-ignore-table选项来匹配该前缀。例如,您可以给所有这样的表命名以norep开头(如norepmytablenorepyourtable等),然后使用--replicate-wild-ignore-table=norep%来阻止它们被复制。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-timeout.html

19.5.1.32 复制重试和超时

系统变量replica_transaction_retries的全局值(从 MySQL 8.0.26 开始)或slave_transaction_retries(在 MySQL 8.0.26 之前)设置了单线程或多线程复制品上应用程序线程在停止之前自动重试失败事务的最大次数。当 SQL 线程由于InnoDB死锁而无法执行事务,或者事务的执行时间超过InnoDB``innodb_lock_wait_timeout值时,事务会自动重试。如果事务有一个阻止其成功的非临时错误,则不会重试。

默认设置为replica_transaction_retriesslave_transaction_retries为 10,意味着在出现明显临时错误的失败事务会在停止应用程序线程之前重试 10 次。将该变量设置为 0 会禁用事务的自动重试。在多线程复制中,指定的事务重试次数可以在所有通道的所有应用程序线程上进行。性能模式表replication_applier_status显示了每个复制通道上发生的事务重试总数,在COUNT_TRANSACTIONS_RETRIES列中。

重试事务的过程可能导致复制品或组复制组成员出现滞后,可以将其配置为单线程或多线程复制品。性能模式表replication_applier_status_by_worker显示了单线程或多线程复制品上应用程序线程重试事务的详细信息。这些数据包括时间戳,显示应用程序线程从开始到结束应用最后一个事务所花费的时间(以及当前正在进行的事务何时开始),以及这是在原始来源和直接来源上提交后多长时间。数据还显示了最后一个事务和当前正在进行的事务的重试次数,并使您能够识别导致事务重试的瞬时错误。您可以使用此信息查看事务重试是否导致复制滞后,并调查导致重试的失败的根本原因。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-timezone.html

19.5.1.33 复制和时区

默认情况下,源和副本服务器假定它们处于相同的时区。如果在不同时区的服务器之间进行复制,则必须在源和副本上设置时区。否则,依赖源本地时间的语句将无法正确复制,例如使用NOW()FROM_UNIXTIME()函数的语句。

请验证源和副本的系统时区(system_time_zone)、服务器当前时区(time_zone的全局值)和会话时区(time_zone的会话值)的设置组合是否产生正确的结果。特别是,如果time_zone系统变量设置为值SYSTEM,表示服务器时区与系统时区相同,则这可能导致源和副本应用不同的时区。例如,源可能在二进制日志中写入以下语句:

SET @@session.time_zone='SYSTEM';

如果此源及其副本对其系统时区设置不同,则即使副本的全局time_zone值已设置为与源相匹配,此语句也可能在副本上产生意外结果。有关 MySQL Server 的时区设置说明以及如何更改它们,请参阅 第 7.1.15 节,“MySQL Server 时区支持”。

请参阅 第 19.5.1.14 节,“复制和系统函数”。

译文:dev.mysql.com/doc/refman/8.0/en/replication-features-transaction-inconsistencies.html

19.5.1.34 复制和事务不一致性

根据您的复制配置,从中继日志中执行的事务序列可能存在不一致性。本节解释了如何避免不一致性并解决其引起的任何问题。

可能存在以下类型的不一致性:

  • 未完成的事务。更新非事务表的事务已应用部分但不是全部更改。

  • 间隙。在外部化事务集中,当给定一个有序的事务序列时,后续序列中的事务在先前序列中的某些其他事务之前应用时,会出现间隙。只有在使用多线程副本时才会出现间隙。

    要避免多线程复制中出现的间隙,请设置replica_preserve_commit_order=ON(从 MySQL 8.0.26 开始)或slave_preserve_commit_order=ON(在 MySQL 8.0.26 之前)。从 MySQL 8.0.27 开始,默认情况下设置此选项,因为从该版本开始,默认情况下所有副本都是多线程的。

    直到 MySQL 8.0.18,保留提交顺序需要启用二进制日志(log_bin)和副本更新日志(log_replica_updateslog_slave_updates),这是从 MySQL 8.0 开始的默认设置。从 MySQL 8.0.19 开始,在副本上设置replica_preserve_commit_order=ONslave_preserve_commit_order=ON不需要启用二进制日志和副本更新日志,并且如果需要,可以禁用。

    在所有版本中,设置replica_preserve_commit_order=ONslave_preserve_commit_order=ON需要设置replica_parallel_type(从 MySQL 8.0.26 开始)或slave_parallel_type(在 MySQL 8.0.26 之前)为LOGICAL_CLOCK。从 MySQL 8.0.27 开始(但不适用于早期版本),这是默认设置。

    在某些特定情况下,如replica_preserve_commit_orderslave_preserve_commit_order的描述中列出的情况,设置replica_preserve_commit_order=ONslave_preserve_commit_order=ON无法在复制品上保留提交顺序,因此在这些情况下,序列中仍可能出现间隙。

    设置replica_preserve_commit_order=ONslave_preserve_commit_order=ON不会阻止源二进制日志位置滞后。

  • 源二进制日志位置滞后。即使没有间隙,也有可能在Exec_master_log_pos之后应用了事务。也就是说,直到点N之前的所有事务都已应用,但在点N之后没有应用任何事务,但Exec_master_log_pos的值小于N。在这种情况下,Exec_master_log_pos是已应用事务的“低水位标记”,落后于最近应用事务的位置。这只会发生在多线程复制中。启用replica_preserve_commit_orderslave_preserve_commit_order不会阻止源二进制日志位置滞后。

以下情景与部分应用事务、间隙和源二进制日志位置滞后有关:

  1. 在复制线程运行时,可能会出现间隙和部分应用事务。

  2. mysqld关闭。无论是干净的还是不干净的关闭都会中止正在进行的事务,并可能留下间隙和部分应用事务。

  3. 复制线程的KILL(在使用单线程复制时为 SQL 线程,在使用多线程复制时为协调器线程)。这会中止正在进行的事务,并可能留下间隙和部分应用事务。

  4. 在应用程序线程中发生错误。这可能会留下间隙。如果错误发生在混合事务中,则该事务将被部分应用。在使用多线程复制时,未收到错误的工作线程会完成它们的队列,因此可能需要一些时间来停止所有线程。

  5. STOP REPLICA 在使用多线程复制时使用。发出 STOP REPLICA 后,复制品等待任何间隙被填充,然后更新 Exec_master_log_pos。这确保它永远不会留下间隙或源二进制日志位置滞后,除非上述任何情况适用,换句话说,在 STOP REPLICA 完成之前,要么发生错误,要么另一个线程发出 KILL,要么服务器重新启动。在这些情况下,STOP REPLICA 返回成功。

  6. 如果中继日志中的最后一个事务仅被部分接收,并且多线程复制的协调器线程已开始将事务调度给工作线程,则 STOP REPLICA 最多等待 60 秒以接收事务。超时后,协调器放弃并中止事务。如果事务是混合的,则可能会留下未完成的部分。

  7. 当正在进行的事务仅更新事务表时,STOP REPLICA 立即回滚并停止。如果正在进行的事务是混合的,STOP REPLICA 最多等待 60 秒以完成事务。超时后,它会中止事务,因此可能会留下未完成的部分。

系统变量 rpl_stop_replica_timeout(从 MySQL 8.0.26 开始)或 rpl_stop_slave_timeout(在 MySQL 8.0.26 之前)的全局设置与停止复制线程的过程无关。它只是使发出 STOP REPLICA 的客户端返回给客户端,但���制线程继续尝试停止。

如果复制通道存在间隙,会产生以下后果:

  1. 复制品数据库处于可能从未存在于源上的状态。

  2. SHOW REPLICA STATUS 中的 Exec_master_log_pos 字段仅是“低水位标记”。换句话说,出现在该位置之前的事务已经提交,但在该位置之后的事务可能已经提交,也可能没有。

  3. 对于该通道,CHANGE REPLICATION SOURCE TOCHANGE MASTER TO 语句将因错误而失败,除非应用程序线程正在运行且语句仅设置接收器选项。

  4. 如果使用--relay-log-recovery启动mysqld,则不会为该通道执行恢复,并会打印警告。

  5. 如果使用--dump-replica--dump-slave来使用mysqldump,它不会记录间隙的存在;因此,它会打印CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO,并将RELAY_LOG_POS设置为Exec_master_log_pos中的“低水位”位置。

    在另一台服务器上应用转储并启动复制线程后,出现在该位置之后的事务将再次被复制。请注意,如果启用了 GTID(但在这种情况下不建议使用--dump-replica--dump-slave),这是无害的。

如果复制通道存在源二进制日志位置滞后但没有间隙,则适用于上述情况 2 至 5,但不适用于情况 1。

源二进制日志位置信息以二进制格式持久化存储在内部表mysql.slave_worker_info中。START REPLICA [SQL_THREAD]始终会查阅此信息,以便仅应用正确的事务。即使在START REPLICA之前将replica_parallel_workersslave_parallel_workers更改为 0,甚至在使用UNTIL子句的情况下使用START REPLICA,这仍然有效。START REPLICA UNTIL SQL_AFTER_MTS_GAPS仅应用所需数量的事务以填补间隙。如果在消耗所有间隙之前告诉START REPLICA停止的UNTIL子句,则会留下剩余的间隙。

警告

RESET REPLICA会删除中继日志并重置复制位置。因此,在具有间隙的多线程复制中发出RESET REPLICA意味着复制丢失了有关间隙的任何信息,而没有纠正间隙。在这种情况下,如果使用基于二进制日志位置的复制,则恢复过程将失败。

当使用基于 GTID 的复制时(GTID_MODE=ON),并且使用CHANGE REPLICATION SOURCE TO语句为复制通道设置了SOURCE_AUTO_POSITION时,旧的中继日志在恢复过程中不再需要。相反,复制品可以使用 GTID 自动定位来计算与源相比缺少的事务。从 MySQL 8.0.26 开始,在使用基于 GTID 的复制时,用于在多线程复制品上解决间隙的基于二进制日志位置的过程将完全跳过。当跳过该过程时,START REPLICA UNTIL SQL_AFTER_MTS_GAPS语句的行为会有所不同,并且不会尝试检查事务序列中的间隙。您还可以发出CHANGE REPLICATION SOURCE TO语句,在非 GTID 复制品上不允许存在间隙的情况下。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-transactions.html

19.5.1.35 复制和事务

在同一事务中混合事务和非事务语句。 一般来说,在复制环境中,应避免更新既有事务表又有非事务表的事务。还应避免使用任何访问既有事务(或临时)表又访问非事务表并写入其中的语句。

服务器使用以下规则进行二进制日志记录:

  • 如果事务中的初始语句是非事务的,则立即写入二进制日志。事务中的其余语句被缓存,直到事务提交时才写入二进制日志。(如果事务回滚,则仅当它们进行不可回滚的非事务更改时,缓存的语句才会写入二进制日志。否则,它们将被丢弃。)

  • 对于基于语句的日志记录,非事务语句的记录受binlog_direct_non_transactional_updates系统变量的影响。当此变量为OFF(默认值)时,记录如上所述。当此变量为ON时,对于事务中发生的任何非事务语句,立即记录(不仅仅是初始的非事务语句)。其他语句被保留在事务缓存中,并在事务提交时记录。binlog_direct_non_transactional_updates对于行格式或混合格式的二进制日志记录没有影响。

事务、非事务和混合语句。 为了应用这些规则,服务器认为一个语句是非事务的,如果它只改变非事务表,而认为是事务的,如果它只改变事务表。一个引用了非事务表和事务表并更新任何涉及的表的语句被视为“混合”语句。混合语句,像事务语句一样,在事务提交时被缓存和记录。

更新事务表的混合语句,如果该语句还执行以下任一操作,则被视为不安全:

  • 更新或读取临时表

  • 读取非事务表且事务隔离级别低于 REPEATABLE_READ

在事务中更新事务表后的混合语句,如果执行以下任一操作,则被视为不安全:

  • 更新任何表并从任何临时表读取

  • 更新非事务表且binlog_direct_non_transactional_updates为关闭状态

更多信息,请参见 Section 19.2.1.3, “Determination of Safe and Unsafe Statements in Binary Logging”.

注意

混合语句与混合二进制日志格式无关。

在事务混合更新事务和非事务表的情况下,二进制日志中语句的顺序是正确的,即使在ROLLBACK的情况下,所有需要的语句也会被写入二进制日志。然而,当第二个连接在第一个连接事务完成之前更新非事务表时,语句可能会因为第二个连接的更新立即写入,而不考虑第一个连接正在执行的事务状态,导致日志顺序混乱。

在源和副本上使用不同的存储引擎。 可以在源上使用非事务表复制事务表到副本上。例如,可以将InnoDB源表复制为MyISAM副本表。但是,如果这样做,在BEGIN ... COMMIT块中停止副本会出现问题,因为副本会在BEGIN块的开头重新启动。

MyISAM表上的事务复制到副本上的事务表,例如使用InnoDB存储引擎的表,也是安全的。在这种情况下,在源上发出的AUTOCOMMIT=1语句会被复制,从而在副本上强制执行AUTOCOMMIT模式。

当副本的存储引擎类型为非事务时,应避免在源上混合更新事务和非事务表的事务,因为它们可能导致源事务表和副本非事务表之间的数据不一致。也就是说,这样的事务可能导致源存储引擎特定行为,可能导致复制失去同步。MySQL 不会对此发出警告,因此在将源上的事务表复制到副本上的非事务表时,应格外小心。

更改事务中的二进制日志格式。 只要事务正在进行中,binlog_formatbinlog_checksum系统变量是只读的。

每个事务(包括autocommit事务)都被记录在二进制日志中,就好像它以BEGIN语句开始,以COMMITROLLBACK语句结束。即使是影响使用非事务性存储引擎(如MyISAM)的表的语句也是如此。

注意

对于仅适用于 XA 事务的限制,请参见第 15.3.8.3 节,“XA 事务的限制”。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-triggers.html

19.5.1.36 复制和触发器

在基于语句的复制中,源上执行的触发器也会在副本上执行。在基于行的复制中,源上执行的触发器不会在副本上执行。相反,源上由触发器执行导致的行更改会被复制并应用到副本上。

这种行为是有意设计的。如果在基于行的复制下,副本服务器应用触发器以及由它们引起的行更改,那么实际上更改会在副本上应用两次,导致源和副本上的数据不同。

如果希望触发器在源和副本上都执行,可能是因为源和副本上有不同的触发器,则必须使用基于语句的复制。然而,为了启用副本端触发器,不必完全使用基于语句的复制。只需在希望产生此效果的语句上切换到基于语句的复制即可,其余时间继续使用基于行的复制。

调用导致对AUTO_INCREMENT列进行更新的触发器(或函数)的语句在使用基于语句的复制时无法正确复制。MySQL 8.0 将这类语句标记为不安全。(Bug #45677)

触发器可以针对不同的触发事件组合(INSERTUPDATEDELETE)和动作时间(BEFOREAFTER)拥有触发器,并且允许多个触发器。

为简洁起见,“多个触发器”在这里是“具有相同触发事件和动作时间的多个触发器”的简称。

升级。 早于 MySQL 5.7 版本不支持多个触发器。如果在使用早于 MySQL 5.7 的版本的复制拓扑中升级服务器,请先升级副本,然后再升级源。如果升级后的复制源服务器仍有使用不支持多个触发器的 MySQL 版本的旧副本,那么如果在源上为已经具有相同触发事件和动作时间的触发器的表创建触发器,则在这些副本上会出现错误。

降级。 如果将支持多个触发器的服务器降级到不支持多个触发器的旧版本,降级会产生以下影响:

  • 对于具有触发器的每个表,所有触发器定义都在该表的.TRG文件中。然而,如果存在具有相同触发事件和动作时间的多个触发器,当触发事件发生时,服务器只会执行其中一个。有关.TRG文件的信息,请参阅 MySQL 服务器 Doxygen 文档中的表触发器存储部分,网址为dev.mysql.com/doc/index-other.html

  • 如果在降级后添加或删除表的触发器,则服务器会重写表的.TRG文件。重写后的文件仅保留每个触发器事件和动作时间组合中的一个触发器;其他触发器将丢失。

为避免这些问题,在降级之前修改您的触发器。对于每个表,如果每个触发器事件和动作时间组合中有多个触发器,请将每组触发器转换为单个触发器,方法如下:

  1. 对于每个触发器,创建一个包含触发器中所有代码的存储过程。使用NEWOLD访问的值可以通过参数传递给存储过程。如果触发器需要代码中的单个结果值,可以将代码放入存储函数中,并让函数返回该值。如果触发器需要代码中的多个结果值,可以将代码放入存储过程中,并使用OUT参数返回这些值。

  2. 删除表的所有触发器。

  3. 为表创建一个新的触发器,调用刚刚创建的存储过程。因此,这个触发器的效果与它替代的多个触发器相同。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-truncate.html

19.5.1.37 复制和 TRUNCATE TABLE

TRUNCATE TABLE通常被视为 DML 语句,因此在二进制日志记录模式为ROWMIXED时,预计会使用基于行的格式进行记录和复制。然而,在以STATEMENTMIXED模式记录或复制时,当事务隔离级别为READ COMMITTEDREAD UNCOMMITTED时,这会导致在使用事务性存储引擎如InnoDB的表时出现问题,这种情况排除了基于语句的记录。

TRUNCATE TABLE在记录和复制方面被视为 DDL 而不是 DML,以便可以将其记录和复制为语句。然而,对于副本上的InnoDB和其他事务性表的影响仍遵循第 15.1.37 节“TRUNCATE TABLE Statement”中描述的规则。 (Bug #36763)

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-user-names.html

19.5.1.38 复制和用户名称长度

MySQL 8.0 中用户名称的最大长度为 32 个字符。 当副本运行的 MySQL 版本早于 5.7 时,长度超过 16 个字符的用户名称的复制将失败,因为这些版本仅支持较短的用户名称。 这仅在从更新的源复制到较旧的副本时发生,这不是推荐的配置。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-variables.html

19.5.1.39 复制和变量

使用STATEMENT模式时,系统变量在使用会话范围时不会被正确复制,除了以下变量:

  • auto_increment_increment

  • auto_increment_offset

  • character_set_client

  • character_set_connection

  • character_set_database

  • character_set_server

  • collation_connection

  • collation_database

  • collation_server

  • foreign_key_checks

  • identity

  • last_insert_id

  • lc_time_names

  • pseudo_thread_id

  • sql_auto_is_null

  • time_zone

  • timestamp

  • unique_checks

当使用MIXED模式时,前述列表中的变量在会话范围内使用时会导致从基于语句的日志记录切换到基于行的日志记录。请参阅 Section 7.4.4.3, “Mixed Binary Logging Format”。

sql_mode也会被复制,除了NO_DIR_IN_CREATE模式;复制品始终保留自己的NO_DIR_IN_CREATE值,而不管源上对其进行了何种更改。这对所有复制格式都适用。

然而,当mysqlbinlog解析SET @@sql_mode = *mode*语句时,包括NO_DIR_IN_CREATE在内的完整mode值将传递给接收服务器。因此,在使用STATEMENT模式时,此类语句的复制可能不安全。

default_storage_engine系统变量不会被复制,无论日志记录模式如何;这旨在促进不同存储引擎之间的复制。

read_only 系统变量不会被复制。此外,启用此变量在不同的 MySQL 版本中对临时表、表锁定和 SET PASSWORD 语句产生不同的影响。

max_heap_table_size 系统变量不会被复制。在源上增加此变量的值而在副本上未这样做最终可能导致在副本上执行 MEMORY 表的 INSERT 语句时出现 Table is full 错误,因为源上的表被允许比副本上的表更大。有关更多信息,请参见 Section 19.5.1.21, “Replication and MEMORY Tables”。

在基于语句的复制中,当在更新表的语句中使用会话变量时,会话变量不会被正确复制。例如,以下语句序列在源和副本上不会插入相同的数据:

SET max_join_size=1000;
INSERT INTO mytable VALUES(@@max_join_size);

这不适用于常见的顺序:

SET time_zone=...;
INSERT INTO mytable VALUES(CONVERT_TZ(..., ..., @@time_zone));

当使用基于行的复制时,会话变量的复制不是问题,此时会话变量始终安全地被复制。参见 Section 19.2.1, “Replication Formats”。

以下会话变量被写入二进制日志,并在解析二进制日志时由副本进行尊重,无论日志格式如何:

  • sql_mode

  • foreign_key_checks

  • unique_checks

  • character_set_client

  • collation_connection

  • collation_database

  • collation_server

  • sql_auto_is_null

重要

尽管与字符集和校对有关的会话变量被写入二进制日志,但不支持不同字符集之间的复制。

为了减少可能的混淆,我们建议您始终在源和副本上使用相同的设置来配置 lower_case_table_names 系统变量,特别是当您在区分大小写的文件系统上运行 MySQL 时。lower_case_table_names 设置只能在初始化服务器时配置。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-views.html

19.5.1.40 复制和视图

视图始终会被复制到副本中。视图是根据其自身名称进行过滤的,而不是根据它们所引用的表进行过滤。这意味着即使视图包含通常会被replication-ignore-table规则过滤掉的表,视图也可以被复制到副本中。因此,应该注意确保视图不会复制通常出于安全原因而被过滤的表数据。

使用基于语句的日志记录支持从表复制到同名视图,但在使用基于行的日志记录时不支持。在启用基于行的日志记录时尝试这样做会导致错误。

19.5.2 MySQL 版本之间的复制兼容性

原文:dev.mysql.com/doc/refman/8.0/en/replication-compatibility.html

MySQL 支持从一个发布系列复制到下一个更高的发布系列。例如,您可以从运行 MySQL 5.6 的源复制到运行 MySQL 5.7 的副本,从运行 MySQL 5.7 的源复制到运行 MySQL 8.0 的副本,依此类推。但是,如果源使用在副本上使用的 MySQL 版本中不再支持的语句或行为,可能会在从旧源复制到新副本时遇到困难。例如,MySQL 8.0 不再支持超过 64 个字符的外键名称。

在涉及多个源的复制设置中,不支持使用两个以上的 MySQL 服务器版本,无论源或副本 MySQL 服务器的数量如何。这个限制不仅适用于发布系列,还适用于同一发布系列中的版本号。例如,如果您正在使用链式或循环复制设置,您不能同时使用 MySQL 8.0.22、MySQL 8.0.24 和 MySQL 8.0.28,尽管您可以同时使用这些版本中的任意两个。

重要提示

强烈建议在给定的 MySQL 发布系列中使用最新版本,因为复制(和其他)功能不断得到改进。还建议在 MySQL 发布系列的早期版本的源和副本可用时升级到 GA(生产)版本。

从 MySQL 8.0.14 开始,二进制日志中为每个事务记录了原始提交事务的服务器版本(original_server_version),以及在复制拓扑中当前服务器的直接源服务器的服务器版本(immediate_server_version)。

从更新的源到旧的副本的复制可能是可能的,但通常不受支持。这是由于许多因素:

  • 二进制日志格式更改。 二进制日志格式可能会在主要版本发布之间发生变化。虽然我们尽力保持向后兼容性,但这并非总是可能的。源可能还启用了旧副本不理解的可选功能,例如二进制日志事务压缩,导致压缩后的事务有效负载无法在 MySQL 8.0.20 之前的版本中被副本读取。

    这也对升级复制服务器有重大影响;有关更多信息,请参阅第 19.5.3 节,“升级复制拓扑”。

  • 有关基于行的复制的更多信息,请参见第 19.2.1 节,“复制格式”。

  • SQL 不兼容性。 如果要复制的语句使用源上可用但在副本上不可用的 SQL 功能,并且使用基于语句的复制从较新的源复制到较旧的副本是不允许的。

    然而,如果源和副本都支持基于行的复制,并且没有需要复制的数据定义语句依赖于源上发现但在副本上找不到的 SQL 功能,则可以使用基于行的复制来复制数据修改语句的效果,即使在源上运行的 DDL 在副本上不受支持。

在 MySQL 8.0.26 中,对复制仪器名称进行了不兼容的更改,包括线程阶段的名称,其中包含术语“master”,被更改为“source”,“slave”,被更改为“replica”,以及“mts”(代表“多线程从属”),被更改为“mta”(代表“多线程应用程序”)。使用这些仪器名称的监控工具可能会受到影响。如果不兼容的更改对您产生影响,请将terminology_use_previous系统变量设置为BEFORE_8_0_26,以使 MySQL Server 使用前面列表中指定对象的旧版本名称。这样可以使依赖于旧名称的监控工具继续工作,直到它们可以更新为使用新名称。

有关潜在复制问题的更多信息,请参见第 19.5.1 节,“复制功能和问题”。

19.5.3 升级复制拓扑

原文:dev.mysql.com/doc/refman/8.0/en/replication-upgrade.html

当您升级参与复制拓扑的服务器时,您需要考虑每个服务器在拓扑中的角色,并注意与复制相关的问题。有关升级 MySQL 服务器实例的一般信息和说明,请参阅第三章,升级 MySQL

如第 19.5.2 节,“MySQL 版本之间的复制兼容性”中所解释的,MySQL 支持从运行一个发布系列的源到运行下一个更高发布系列的副本的复制,但不支持从运行较新发布的源到运行较早发布的副本的复制。较早发布的副本可能没有处理源在较新发布中可以处理的事务所需的能力。因此,在升级源服务器到目标发布之前,您必须将复制拓扑中的所有副本升级到目标 MySQL 服务器版本。这样,您永远不会出现仍在较早发布的副本尝试处理来自较新发布源的事务的情况。

在存在多个源(多源复制)的复制拓扑中,不支持使用两个以上的 MySQL 服务器版本,无论源或副本 MySQL 服务器的数量如何。此限制不仅适用于发布系列,还适用于同一发布系列中的版本号。例如,在这样的设置中,您不能同时使用 MySQL 8.0.22、MySQL 8.0.24 和 MySQL 8.0.28,尽管您可以同时使用这些版本中的任意两个。

如果您需要降级复制拓扑中的服务器,则必须在降级副本之前降级源。在副本上,您必须确保二进制日志和中继日志已完全处理,并在继续降级之前将其删除。

发行版之间的行为变化

虽然这个升级顺序是正确的,但在从一个尚未升级的早期版本源复制到一个已经升级的后续版本副本时,仍然可能遇到复制困难。如果源使用了在副本上安装的后续版本中不再支持的语句或依赖行为,这种情况可能发生。您可以使用 MySQL Shell 的升级检查工具util.checkForServerUpgrade()来检查 MySQL 5.7 服务器实例或 MySQL 8.0 服务器实例是否可以升级到 GA MySQL 8.0 版本。该工具识别需要修复的任何内容,以确保在升级后不会出现问题,包括在后续版本中不再可用的功能和行为。有关升级检查工具的信息,请参见升级检查工具。

如果您正在将现有的 MySQL 版本不支持全局事务标识符(GTID)的复制设置升级到支持 GTID 的版本,则只有在确保设置符合基于 GTID 的复制的所有要求时,才在源和副本上启用 GTID。有关将基于二进制日志文件位置的复制设置转换为使用基于 GTID 的复制的信息,请参见 Section 19.1.3.4, “Setting Up Replication Using GTIDs”。

在严格 SQL 模式下(STRICT_TRANS_TABLESSTRICT_ALL_TABLES)影响操作的更改可能导致升级后副本的复制失败。如果使用基于语句的日志记录(binlog_format=STATEMENT),如果副本在源之前升级,源执行的语句在那里成功,但在副本上可能失败,从而导致复制停止。为了解决这个问题,停止源上的所有新语句,并等待副本赶上,然后升级副本。或者,如果无法停止新语句,暂时在源上切换到基于行的日志记录(binlog_format=ROW),并等待所有副本处理到达此更改点之前产生的所有二进制日志,然后升级副本。

默认字符集从latin1更改为utf8mb4在 MySQL 8.0 中。在复制设置中,当从 MySQL 5.7 升级到 8.0 时,建议在升级之前将默认字符集更改回 MySQL 5.7 中使用的字符集。升级完成后,可以将默认字符集更改为utf8mb4。假设之前使用了默认设置,保留它们的一种方法是在my.cnf文件中使用以下行启动服务器:

[mysqld]
character_set_server=latin1
collation_server=latin1_swedish_ci

标准升级程序

要升级复制拓扑,请按照第三章“升级 MySQL”中的说明为每个单独的 MySQL 服务器实例执行此整体过程:

  1. 首先升级副本。在每个副本实例上:

    • 执行第 3.6 节“准备升级安装”中描述的初步检查和步骤。

    • 关闭 MySQL 服务器。

    • 升级 MySQL 服务器二进制文件或软件包。

    • 重新启动 MySQL 服务器。

    • 如果您已升级到早于 MySQL 8.0.16 的版本,请手动调用mysql_upgrade来升级系统表和模式。当服务器以全局事务标识符(GTIDs)启用时(gtid_mode=ON),不要通过mysql_upgrade启用二进制日志记录(因此不要使用--write-binlog选项)。然后关闭并重新启动服务器。

    • 如果您已升级到 MySQL 8.0.16 或更高版本,请不要调用mysql_upgrade。从该版本开始,MySQL 服务器将执行整个 MySQL 升级过程,在升级过程中禁用二进制日志记录。

    • 使用START REPLICASTART SLAVE语句重新启动复制。

  2. 当所有副本都已升级时,按照相同步骤升级和重新启动源服务器,但不包括START REPLICASTART SLAVE语句。如果您对基于行的日志记录或默认字符集进行了临时更改,现在可以恢复更改。

使用表修复或重建的升级过程

在从一个 MySQL 系列移动到下一个系列时,某些升级可能需要您删除并重新创建数据库对象。例如,排序规则更改可能需要重建表索引。如果需要这样的操作,则在第 3.5 节“MySQL 8.0 中的更改”中有详细说明。最安全的做法是在副本和源上分别执行这些操作,并禁用从源到副本的这些操作的复制。为此,请使用以下过程:

  1. 停止所有复制实例并升级二进制文件或软件包。使用--skip-slave-start选项或从 MySQL 8.0.24 开始,使用skip_slave_start系统变量重新启动它们,以便它们不连接到源。执行任何需要重新创建数据库对象的表修复或重建操作,例如使用REPAIR TABLEALTER TABLE,或者转储和重新加载表或触发器。

  2. 在源上禁用二进制日志。要在不重新启动源的情况下执行此操作,请执行SET sql_log_bin = OFF语句。或者,停止源并使用--skip-log-bin选项重新启动它。如果重新启动源,则可能还希望禁止客户端连接。例如,如果所有客户端都使用 TCP/IP 连接,请在重新启动源时启用skip_networking系统变量。

  3. 禁用二进制日志后,执行任何需要重新创建数据库对象的表修复或重建操作。在此步骤中必须禁用二进制日志,以防止这些操作被记录并稍后发送到复制实例。

  4. 在源上重新启用二进制日志。如果之前将sql_log_bin设置为OFF,则执行SET sql_log_bin = ON语句。如果重新启动源以禁用二进制日志,请在不使用--skip-log-bin的情况下重新启动,并且不启用skip_networking系统变量,以便客户端和复制实例可以连接。

  5. 重新启动复制实例,这次不使用--skip-slave-start选项或skip_slave_start系统变量。

19.5.4 复制故障排除

原文:dev.mysql.com/doc/refman/8.0/en/replication-problems.html

如果您已按照说明操作,但复制设置无法正常工作,首先要做的是检查错误日志中的消息。许多用户在遇到问题后没有及时这样做而浪费了时间。

如果您无法从错误日志中确定问题所在,请尝试以下技术:

  • 验证源是否启用了二进制日志记录,通过发出SHOW MASTER STATUS语句进行验证。二进制日志记录默认启用。如果启用了二进制日志记录,则Position不为零。如果未启用二进制日志记录,请验证您是否未使用任何禁用二进制日志记录的设置运行源,例如--skip-log-bin选项。

  • 验证server_id系统变量在源和副本上启动时是否已设置,并且 ID 值在每台服务器上是唯一的。

  • 验证副本是否正在运行。使用SHOW REPLICA STATUS检查Replica_IO_RunningReplica_SQL_Running的值是否都为Yes。如果不是,请验证启动副本服务器时使用的选项。例如,--skip-slave-start命令行选项,或者从 MySQL 8.0.24 开始,skip_slave_start系统变量,阻止复制线程启动,直到您发出START REPLICA语句。

  • 如果副本正在运行,请检查它是否已经与源建立连接。使用SHOW PROCESSLIST,找到 I/O(接收器)和 SQL(应用程序)线程,并检查它们的State列以查看显示的内容。参见 Section 19.2.3, “Replication Threads”。如果接收器线程状态显示Connecting to master,请检查以下内容:

    • 验证源上复制用户的权限。

    • 检查源的主机名是否正确,并确保您使用正确的端口连接到源。用于复制的端口与用于客户端网络通信的端口相同(默认为3306)。对于主机名,请确保名称解析为正确的 IP 地址。

    • 检查配置文件,查看源或副本上是否启用了skip_networking系统变量以禁用网络。如果是,请注释该设置或将其删除。

    • 如果源有防火墙或 IP 过滤配置,请确保用于 MySQL 的网络端口未被过滤。

    • 通过使用pingtraceroute/tracert到达主机来检查是否可以访问源。

  • 如果副本以前正在运行但已停止,则原因通常是在源上成功运行的某个语句在副本上失败。如果您已经正确地对源进行了快照,并且从未在复制线程之外修改副本上的数据,则不应该发生这种情况。如果副本意外停止,则是一个错误,或者您遇到了 Section 19.5.1, “Replication Features and Issues”中描述的已知复制限制之一。如果是错误,请参阅 Section 19.5.5, “How to Report Replication Bugs or Problems”,了解如何报告。

  • 如果在源上成功运行的语句在副本上拒绝运行,请尝试以下步骤,如果不可行,则无法通过删除副本的数据库并从源复制新快照进行完整数据库重新同步:

    1. 确定副本上受影响的表是否与源表不同。尝试理解是如何发生的。然后使副本的表与源的表相同,并运行START REPLICA

    2. 如果前面的步骤不起作用或不适用,请尝试理解是否可以安全地手动进行更新(如果需要),然后忽略源的下一个语句。

    3. 如果您决定副本可以跳过源的下一个语句,请发出以下语句:

      mysql> SET GLOBAL sql_slave_skip_counter = *N*;
      mysql> START SLAVE;
      
      Or from MySQL 8.0.26:
      mysql> SET GLOBAL sql_replica_skip_counter = *N*;
      mysql> START REPLICA;
      

      如果下一个来自源的语句不使用AUTO_INCREMENTLAST_INSERT_ID(),则N的值应为 1。否则,该值应为 2。对于使用AUTO_INCREMENTLAST_INSERT_ID()的语句使用值 2 的原因是它们在源的二进制日志中占据两个事件。

      参见 SET GLOBAL sql_slave_skip_counter 语法。

    4. 如果您确定副本最初与源完全同步,并且没有人在复制线程之外更新涉及的表,则差异可能是由错误引起的。如果您正在运行最新版本的 MySQL,请报告问题。如果您正在运行旧版本,请尝试升级到最新的生产版本以确定问题是否仍然存在。

19.5.5 如何报告复制 Bug 或问题

原文:dev.mysql.com/doc/refman/8.0/en/replication-bugs.html

当确定没有用户错误涉及,并且复制仍然无法正常工作或不稳定时,是时候向我们发送 bug 报告了。我们需要尽可能多地从您那里获取信息以便追踪 bug。请花些时间和精力准备一个好的 bug 报告。

如果您有一个可重现的测试用例来演示 bug,请按照第 1.5 节“如何报告 Bug 或问题”中给出的说明将其输入到我们的 bug 数据库中。如果您遇到“幻影”问题(即您无法随意复制的问题),请使用以下步骤:

  1. 验证没有用户错误涉及。例如,如果您在复制线程之外更新复制端,数据将不同步,更新时可能会出现唯一键冲突。在这种情况下,复制线程会停止并等待您手动清理表以将其带入同步状态。这不是一个复制问题。这是外部干扰导致复制失败的问题。

  2. 确保复制端正在运行并启用了二进制日志记录(log_bin 系统变量),并启用了 --log-slave-updates 选项,这会导致复制端将从源端接收的更新记录到自己的二进制日志中。这些设置是默认设置。

  3. 在重置复制状态之前,请保存所有证据。如果我们没有信息或只有零碎的信息,那么追踪问题将变得困难或不可能。您应该收集的证据包括:

    • 所有来自源端的二进制日志文件

    • 所有来自复制端的二进制日志文件

    • 源端在发现问题时的SHOW MASTER STATUS输出

    • 源端在发现问题时的SHOW REPLICA STATUS输出

    • 源端和复制端的错误日志

  4. 使用mysqlbinlog来检查二进制日志。以下内容应有助于找到问题陈述。log_filelog_posSHOW REPLICA STATUS中的Master_Log_FileRead_Master_Log_Pos值。

    $> mysqlbinlog --start-position=*log_pos* *log_file* | head
    

在收集了问题的证据之后,首先尝试将其作为一个独立的测试用例进行隔离。然后,按照第 1.5 节,“如何报告错误或问题”中的说明,尽可能多地输入问题信息到我们的错误数据库中。

第二十章 组复制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication.html

目录

20.1 组复制背景

20.1.1 复制技术

20.1.2 组复制用例

20.1.3 多主和单主模式

20.1.4 组复制服务

20.1.5 组复制插件架构

20.2 开始使用

20.2.1 在单主模式下部署组复制

20.2.2 本地部署组复制

20.3 要求和限制

20.3.1 组复制要求

20.3.2 组复制限制

20.4 监控组复制

20.4.1 GTIDs 和组复制

20.4.2 组复制服务器状态

20.4.3 复制组成员表

20.4.4 复制组成员统计表

20.5 组复制操作

20.5.1 配置在线组

20.5.2 重新启动组

20.5.3 事务一致性保证

20.5.4 分布式恢复

20.5.5 支持 IPv6 和混合 IPv6 和 IPv4 组

20.5.6 使用 MySQL 企业备份与组复制

20.6 组复制安全

20.6.1 用于连接安全管理的通信堆栈

20.6.2 使用安全套接字层(SSL)保护组通信连接

20.6.3 保护分布式恢复连接

20.6.4 组复制 IP 地址权限

20.7 组复制性能和故障排除

20.7.1 调整组通信线程

20.7.2 流量控制

20.7.3 单一一致性领导者

20.7.4 消息压缩

20.7.5 消息分段

20.7.6 XCom 缓存管理

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

20.7.8 处理网络分区和失去法定人数

20.7.9 使用 Performance Schema Memory Instrumentation 监控 Group Replication 内存使用

20.8 升级 Group Replication

20.8.1 在组中组合不同的成员版本

20.8.2 Group Replication 离线升级

20.8.3 Group Replication 在线升级

20.9 Group Replication 变量

20.9.1 Group Replication 系统变量

20.9.2 Group Replication 状态变量

20.10 常见问题解答

本章介绍了 MySQL Group Replication 以及如何安装、配置和监控组。MySQL Group Replication 可以创建弹性、高可用、容错的复制拓扑。

组可以以单一主模式运行,具有自动主选举功能,每次只有一个服务器接受更新。另外,组也可以以多主模式部署,所有服务器都可以接受更新,即使它们同时发出。

有一个内置的组成员服务,保持组的视图在任何给定时间点对所有服务器一致和可用。服务器可以离开和加入组,视图会相应更新。有时服务器可能意外离开组,此时故障检测机制会检测到并通知组视图已更改。这一切都是自动的。

Group Replication 保证数据库服务持续可用。然而,重要的是要理解,如果组中的一个成员不可用,连接到该组成员的客户端必须被重定向或故障转移到组中的另一台服务器,使用连接器、负载均衡器、路由器或某种中间件。Group Replication 没有内置的方法来做到这一点。例如,参见 MySQL Router 8.0。

组复制作为 MySQL Server 的一个插件提供。您可以按照本章的说明在您想要的每个服务器实例上配置插件,启动组,并监视和管理组。部署 MySQL 服务器实例组的另一种方法是使用 InnoDB Cluster。

提示

要部署多个 MySQL 实例,您可以使用 InnoDB Cluster,它使您能够轻松管理一组 MySQL 服务器实例在 MySQL Shell 中。InnoDB Cluster 将 MySQL Group Replication 包装在一个编程环境中,使您可以轻松部署一组 MySQL 实例以实现高可用性。此外,InnoDB Cluster 与 MySQL Router 无缝接口,使您的应用程序可以连接到集群而无需编写自己的故障转移过程。然而,对于不需要高可用性的类似用例,您可以使用 InnoDB ReplicaSet。有关 MySQL Shell 的安装说明,请参见这里。

本章结构如下:

  • 第 20.1 节,“组复制背景” 介绍了组和组复制的工作原理。

  • 第 20.2 节,“入门指南” 解释了如何配置多个 MySQL Server 实例以创建一个组。

  • 第 20.3 节,“需求和限制” 解释了组复制的架构和设置需求以及限制。

  • 第 20.4 节,“监控组复制” 解释了如何监控一个组。

  • 第 20.5 节,“组复制操作” 解释了如何操作一个组。

  • 第 20.6 节,“组复制安全” 解释了如何保护一个组。

  • 第 20.7 节,“组复制性能和故障排除” 解释了如何为一个组调整性能。

  • 第 20.8 节,“升级组复制” 解释了如何升级一个组。

  • 第 20.9 节,“组复制变量” 是特定于组复制的系统变量的参考。

  • 第 20.10 节,“常见问题” 提供了关于部署和操作群组复制的一些技术问题的答案。

20.1 Group Replication 背景

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-background.html

20.1.1 Replication Technologies

20.1.2 Group Replication Use Cases

20.1.3 Multi-Primary and Single-Primary Modes

20.1.4 Group Replication Services

20.1.5 Group Replication Plugin Architecture

本节提供了关于 MySQL Group Replication 的背景信息。

创建容错系统最常见的方法是通过使组件冗余化,换句话说,组件可以被移除而系统应该继续按预期运行。这带来了一系列挑战,将这些系统的复杂性提升到一个全新的水平。具体来说,复制的数据库必须处理这样一个事实,即它们需要维护和管理多台服务器,而不仅仅是一台。此外,由于服务器合作创建组,因此必须处理一些其他经典的分布式系统问题,例如网络分区或脑裂场景。

因此,最终的挑战是将数据库和数据复制的逻辑与多台服务器以一致且简单的方式协调的逻辑融合在一起。换句话说,让多台服务器就系统状态和每次系统经历的变化的数据达成一致意见。这可以总结为使服务器就每个数据库状态转换达成一致意见,以便它们都像一个单一数据库一样前进,或者最终收敛到相同的状态。这意味着它们需要作为(分布式)状态机运行。

MySQL Group Replication 提供了具有强大协调功能的分布式状态机复制。当服务器属于同一组时,它们会自动协调。该组可以在单主模式下运行,具有自动主选举,每次只有一台服务器接受更新。或者,对于更高级的用户,该组可以部署在多主模式下,其中所有服务器都可以接受更新,即使它们同时发出。这种功能是以应用程序必须解决这些部署所施加的限制为代价的。

存在一个内置的组成员服务,使组的视图在任何给定时间点对所有服务器保持一致和可用。服务器可以离开和加入组,视图会相应更新。有时服务器可能意外离开组,此时故障检测机制会检测到这一点,并通知组视图已更改。这一切都是自动的。

要使交易提交,大多数组成员必须就给定交易在全局交易序列中的顺序达成一致。决定提交或中止交易是每个服务器单独完成的,但所有服务器都做出相同的决定。如果出现网络分区,导致成员无法达成一致,那么系统将在解决此问题之前不会继续进行。因此,系统还具有内置的、自动的、防止脑裂的机制。

所有这些都由提供的群组通信系统(GCS)协议驱动。这些协议提供了故障检测机制、群组成员服务以及安全和完全有序的消息传递。所有这些属性对于创建一个确保数据在服务器组中一致复制的系统至关重要。在这项技术的核心是 Paxos 算法的实现。它充当群组通信引擎。

20.1.1 复制技术

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-replication-technologies.html

20.1.1.1 源到副本复制

20.1.1.2 集群复制

在深入了解 MySQL 集群复制之前,本节介绍了一些背景概念以及工作原理的概述。这提供了一些背景信息,帮助理解集群复制所需的条件以及经典异步 MySQL 复制与集群复制之间的区别。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-primary-secondary-replication.html

20.1.1.1 源到副本复制

传统的 MySQL 复制 提供了一种简单的源到副本的复制方法。源是主服务器,副本是从服务器。源应用事务,提交它们,然后稍后(因此是异步的)将它们发送到副本以重新执行(在基于语句的复制中)或应用(在基于行的复制中)。这是一个共享无系统,所有服务器默认都有完整的数据副本。

图 20.1 MySQL 异步复制

源接收的事务被执行,写入二进制日志,然后提交,并向客户端应用程序发送响应。二进制日志中的记录被发送到副本 1 和副本 2 的中继日志,然后在源上进行提交。在每个副本上,事务被应用,写入副本的二进制日志,并提交。源上的提交和副本上的提交都是独立的和异步的。

还有半同步复制,它在协议中添加了一个同步步骤。这意味着主服务器在应用时等待副本确认已接收事务。只有在副本确认接收事务后,主服务器才恢复提交操作。

图 20.2 MySQL 半同步复制

源接收的事务被执行并写入二进制日志。二进制日志中的记录被发送到副本 1 和副本 2 的中继日志。然后源等待副本的确认。当两个副本都返回确认后,源提交事务,并向客户端应用程序发送响应。每个副本返回确认后,应用事务,将其写入二进制日志,并提交。源的提交取决于副本的确认,但副本的提交彼此独立,与源的提交独立。

在这两幅图中有一个经典的异步 MySQL 复制协议的图示(以及其半同步变体)。不同实例之间的箭头代表服务器之间或服务器与客户端应用程序之间交换的消息。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-summary.html

20.1.1.2 Group Replication

Group Replication 是一种可用于实现容错系统的技术。复制组是一组每个服务器都拥有自己完整数据副本的服务器(共享无内容复制方案),并通过消息传递相互交互。通信层提供了一组保证,如原子消息和总顺消息传递。这些是非常强大的属性,可以转化为非常有用的抽象,可以用来构建更高级的数据库复制解决方案。

MySQL Group Replication 建立在这些属性和抽象之上,并实现了一个多源更新的复制协议。一个复制组由多个服务器组成,组中的每个服务器可以随时独立执行事务。然而,所有读写事务只有在组批准后才提交。换句话说,对于任何读写事务,组都需要决定是否提交,因此提交操作不是来自原始服务器的单方面决定。只读事务在组内不需要协调,立即提交。

当一个读写事务在原始服务器准备提交时,服务器会原子地广播写入值(已更改的行)和相应的写入集(已更新行的唯一标识符)。由于事务通过原子广播发送,组中的所有服务器都会接收到事务,或者都不会接收到。如果它们接收到了,那么它们都会按照与之前发送的其他事务相同的顺序接收它。因此,所有服务器以相同的顺序接收相同的事务集,并为事务建立了全局总顺序。

然而,在不同服务器上并发执行的事务之间可能存在冲突。这种冲突是通过检查和比较两个不同且并发事务的写入集来检测的,在一个称为认证的过程中。在认证过程中,冲突检测是在行级别进行的:如果两个并发事务,在不同服务器上执行,更新了相同的行,则存在冲突。冲突解决程序规定,首先被排序的事务在所有服务器上提交,而第二个被排序的事务中止,因此在原始服务器上回滚,并被组中的其他服务器丢弃。例如,如果 t1 和 t2 在不同站点并发执行,都更改了相同的行,并且 t2 在 t1 之前被排序,那么 t2 赢得冲突,t1 被回滚。实际上,这是一个分布式的“先提交者获胜”规则。请注意,如果两个事务往往会发生冲突,那么将它们放在同一服务器上开始是一个好的做法,这样它们有机会在本地锁管理器上同步,而不是由于认证的结果而被回滚。

为了应用和外部化经过认证的事务,集群复制允许服务器偏离事务的约定顺序,如果这不会破坏一致性和有效性。集群复制是一个最终一致性系统,意味着一旦传入流量减少或停止,所有组成员都具有相同的数据内容。在流量流动时,事务可以以稍微不同的顺序外部化,或者在某些成员之前外部化。例如,在多主模式下,一个本地事务可能会在认证后立即外部化,尽管一个在全局顺序中较早的远程事务尚未被应用。当认证过程已经确定事务之间没有冲突时,这是允许的。在单主模式下,在主服务器上,存在一个小概率,即并发的、非冲突的本地事务可能会按照与集群复制约定的全局顺序不同的顺序提交和外部化。在不接受来自客户端的写入的从属服务器上,事务总是按照约定的顺序提交和外部化。

以下图描述了 MySQL 集群复制协议,并通过将其与 MySQL 复制(甚至 MySQL 半同步复制)进行比较,您可以看到一些差异。为了清晰起见,这张图片中省略了一些底层共识和 Paxos 相关的消息。

图 20.3 MySQL 集群复制协议

Source 1 收到的交易被执行。然后,Source 1 向复制组发送消息,该组由自身、Source 2 和 Source 3 组成。当三个成员达成共识时,它们认证交易。Source 1 然后将交易写入其二进制日志,提交它,并向客户端应用程序发送响应。Source 2 和 Source 3 将交易写入其中继日志,然后应用它,写入二进制日志,并提交它。

20.1.2 Group Replication 使用案例

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-use-cases.html

Group Replication 可以让您创建具有冗余性的容错系统,通过将系统状态复制到一组服务器。即使其中一些服务器随后失败,只要不是全部或大多数,系统仍然可用。根据失败的服务器数量,群组可能会有性能或可伸缩性下降,但仍然可用。服务器故障是隔离的和独立的。它们由一个依赖于分布式故障检测器的群组成员服务跟踪,该故障检测器能够在任何服务器离开群组时发出信号,无论是自愿离开还是由于意外停止。有一个分布式恢复过程,确保当服务器加入群组时,它们会自动更新。不需要服务器故障转移,而多源更新到处的特性确保即使单个服务器故障,更新也不会被阻塞。总之,MySQL Group Replication 保证数据库服务持续可用。

重要的是要理解,尽管数据库服务可用,但在发生意外服务器退出时,连接到它的客户端必须被重定向或故障转移到另一台服务器。这不是 Group Replication 试图解决的问题。连接器、负载均衡器、路由器或某种形式的中间件更适合处理这个问题。例如,请参阅 MySQL Router 8.0。

总结一下,MySQL Group Replication 提供了一个高可用、高弹性、可靠的 MySQL 服务。

提示

要部署多个 MySQL 实例,您可以使用 InnoDB Cluster,它使您能够在 MySQL Shell 中轻松管理一组 MySQL 服务器实例。InnoDB Cluster 在一个编程环境中封装了 MySQL Group Replication,使您可以轻松部署一组 MySQL 实例以实现高可用性。此外,InnoDB Cluster 与 MySQL Router 无缝接口,使您的应用程序可以连接到集群而无需编写自己的故障转移过程。然而,对于不需要高可用性的类似用例,您可以使用 InnoDB ReplicaSet。MySQL Shell 的安装说明可以在这里找到。

示例用例

以下示例是 Group Replication 的典型用例。

  • 弹性复制 - 需要非常灵活的复制基础设施的环境,在这种环境中,服务器数量必须能够动态增长或收缩,并且副作用尽可能少。例如,云端的数据库服务。

  • 高可用碎片 - 分片是实现写扩展的流行方法。使用 MySQL 集群复制来实现高可用碎片,其中每个碎片映射到一个复制组。

  • 替代异步源-副本复制 - 在某些情况下,使用单个源服务器会使其成为一个争用点。在某些情况下,向整个组写入可能更具可扩展性。

  • 自主系统 - 此外,您可以纯粹为内置于复制协议中的自动化部署 MySQL 集群复制(在本章和前几章中已经描述)。

20.1.3 多主和单主模式

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-deploying-in-multi-primary-or-single-primary-mode.html

20.1.3.1 单主模式

20.1.3.2 多主模式

Group Replication 可以在单主模式或多主模式下运行。该组的模式是一个全组配置设置,由group_replication_single_primary_mode系统变量指定,所有成员必须相同。ON表示单主模式,这是默认模式,OFF表示多主模式。不可能让组的成员以不同模式部署,例如一个成员配置为多主模式,而另一个成员处于单主模式。

在 Group Replication 运行时无法手动更改group_replication_single_primary_mode的值。从 MySQL 8.0.13 开始,您可以使用group_replication_switch_to_single_primary_mode()group_replication_switch_to_multi_primary_mode()函数在 Group Replication 仍在运行时将组从一种模式转换到另一种模式。这些函数管理更改组模式的过程,并确保数据的安全性和一致性。在早期版本中,要更改组的模式,您必须停止 Group Replication 并在所有成员上更改group_replication_single_primary_mode的值。然后执行组的完全重启(由具有group_replication_bootstrap_group=ON的服务器引导)以实施对新操作配置的更改。您无需重新启动服务器。

无论部署模式如何,Group Replication 不处理客户端故障转移。这必须由中间件框架(如 MySQL Router 8.0)、代理、连接器或应用程序本身处理。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-single-primary-mode.html

20.1.3.1 单主模式

在单主模式下(group_replication_single_primary_mode=ON),组具有一个被设置为读写模式的单主服务器。组中的所有其他成员都被设置为只读模式(使用super_read_only=ON)。主服务器通常是第一个引导组的服务器。加入组的所有其他服务器都会了解主服务器并自动设置为只读模式。

在单主模式下,组复制要求只有一个服务器写入组,因此与多主模式相比,一致性检查可以更宽松,DDL 语句不需要额外小心处理。选项group_replication_enforce_update_everywhere_checks用于启用或禁用组的严格一致性检查。在部署单主模式或将组更改为单主模式时,必须将此系统变量设置为OFF

被指定为主服务器的成员可以通过以下方式更改:

  • 如果现有的主服务器离开组,无论是自愿还是意外,新的主服务器将自动选举产生。

  • 您可以使用group_replication_set_as_primary()函数指定特定成员作为新的主服务器。

  • 如果使用group_replication_switch_to_single_primary_mode()函数将运行在多主模式下的组更改为单主模式,新的主服务器将自动选举产生,或者您可以通过该函数指定新的主服务器。

这些函数只能在所有组成员运行 MySQL 8.0.13 或更高版本时使用。当新的主服务器自动选举产生或手动指定时,它会自动设置为读写模式,其他组成员保持为从服务器,因此为只读模式。图 20.4, “新主服务器选举”展示了这个过程。

图 20.4 新主服务器选举

部署为互连组的五个服务器实例,S1、S2、S3、S4 和 S5。服务器 S1 是主要服务器。写客户端正在与服务器 S1 通信,读客户端正在与服务器 S4 通信。然后,服务器 S1 失败,导致与写客户端的通信中断。然后,服务器 S2 接管为新的主要服务器,现在写客户端与服务器 S2 通信。

当新的主要被选举或任命时,它可能有一些在旧主要上已应用但尚未应用在此服务器上的更改积压。在这种情况下,直到新的主要赶上旧的主要,读写事务可能会导致冲突并被回滚,只读事务可能会导致过时读取。如果激活并正确调整了 Group Replication 的流量控制机制,它将减少快速和慢速成员之间的差异,从而降低发生这种情况的机会。有关流量控制的更多信息,请参见第 20.7.2 节,“流量控制”。从 MySQL 8.0.14 开始,您还可以使用group_replication_consistency系统变量来配置组的事务一致性级别,以防止此问题。设置BEFORE_ON_PRIMARY_FAILOVER(或任何更高的一致性级别)将新事务保留在新选举的主要上,直到积压被应用。有关事务一致性的更多信息,请参见第 20.5.3 节,“事务一致性保证”。如果组未使用流量控制和事务一致性保证,等待新主要应用其与复制相关的中继日志再将客户端应用程序重新路由到它是一个良好的做法。

20.1.3.1.1 主要选举算法

自动主要成员选举过程涉及每个成员查看组的新视图,对潜在的新主要成员进行排序,并选择符合条件的最合适的成员。每个成员在本地做出自己的决定,遵循其 MySQL Server 版本中的主要选举算法。因为所有成员必须达成相同的决定,如果其他组成员运行较低版本的 MySQL Server,则成员会调整其主要选举算法,以使其与组中具有最低 MySQL Server 版本的成员具有相同的行为。

成员在选举主要时考虑的因素按顺序如下:

  1. 考虑的第一个因素是哪个成员或哪些成员正在运行最低版本的 MySQL 服务器。如果所有组成员都在运行 MySQL 8.0.17 或更高版本,则首先按照其发布的补丁版本对成员进行排序。如果有任何成员正在运行 MySQL 服务器 5.7 或 MySQL 8.0.16 或更低版本,则首先按照其发布的主要版本对成员进行排序,而忽略补丁版本。

  2. 如果有多个成员运行最低版本的 MySQL 服务器,则考虑的第二个因素是每个成员的成员权重,由成员上的group_replication_member_weight系统变量指定。如果组中的任何成员正在运行 MySQL 服务器 5.7,在那里这个系统变量不可用,则忽略此因素。

    group_replication_member_weight系统变量指定一个范围为 0-100 的数字。所有成员的默认权重为 50,因此将权重设置为低于此值以降低其排序,将权重设置为高于此值以增加其排序。您可以使用此加权函数来优先使用更好的硬件或确保在主服务器计划维护期间故障转移到特定成员。

  3. 如果有多个成员运行最低版本的 MySQL 服务器,并且其中有多个成员具有最高的成员权重(或正在忽略成员权重),则考虑的第三个因素是每个成员生成的服务器 UUID 的词典顺序,由server_uuid系统变量指定。具有最低服务器 UUID 的成员被选择为主服务器。此因素充当保证和可预测的决定者,以便如果没有任何重要因素可以确定,则所有组成员达成相同的决定。

20.1.3.1.2 找到主服务器

要找出在单主模式下当前是主服务器的服务器,请使用performance_schema.replication_group_members表中的MEMBER_ROLE列。例如:

mysql> SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
+-------------------------+-------------+
| MEMBER_HOST             | MEMBER_ROLE |
+-------------------------+-------------+
| remote1.example.com     | PRIMARY     |
| remote2.example.com     | SECONDARY   |
| remote3.example.com     | SECONDARY   |
+-------------------------+-------------+

警告

group_replication_primary_member状态变量已被弃用,并计划在将来的版本中删除。

或者使用group_replication_primary_member状态变量。

mysql> SHOW STATUS LIKE 'group_replication_primary_member'

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-multi-primary-mode.html

20.1.3.2 多主模式

在多主模式(group_replication_single_primary_mode=OFF)中,没有任何成员担任特殊角色。任何与其他组成员兼容的成员在加入组时被设置为读写模式,并且可以处理写事务,即使这些事务是并发发出的。

如果某个成员停止接受写事务,例如,出现意外服务器退出的情况,连接到该成员的客户端可以被重定向或故障转移至任何处于读写模式的其他成员。Group Replication 本身不处理客户端故障转移,因此您需要使用中间件框架(如 MySQL Router 8.0)、代理、连接器或应用程序本身来安排这一点。图 20.5,“客户端故障转移” 显示了客户端如何在成员离开组时重新连接到另一个组成员。

图 20.5 客户端故障转移

部署了五个服务器实例,S1、S2、S3、S4 和 S5,作为一个互连的组。所有服务器都是主服务器。写客户端正在与服务器 S1 和 S2 通信,读客户端正在与服务器 S4 通信。然后,服务器 S1 发生故障,导致与其写客户端的通信中断。该客户端重新连接到服务器 S3。

Group Replication 是一个最终一致性系统。这意味着一旦传入流量减少或停止,所有组成员都具有相同的数据内容。在流量流动时,事务可以在某些成员上外部化,然后在其他成员上,特别是如果某些成员的写吞吐量较低,则可能导致过时读取的可能性。在多主模式下,较慢的成员也可能积累过多的待认证和应用的事务,导致冲突和认证失败的风险增加。为了限制这些问题,您可以激活和调整 Group Replication 的流量控制机制,以最小化快速和慢速成员之间的差异。有关流量控制的更多信息,请参见第 20.7.2 节,“流量控制”。

从 MySQL 8.0.14 开始,如果您希望对组中的每个事务都有事务一致性保证,可以使用group_replication_consistency系统变量来实现。您可以选择适合组工作负载和数据读写优先级的设置,考虑到增加一致性所需的同步对性能的影响。您还可以为单个会话设置系统变量,以保护特别关注并发性的事务。有关事务一致性的更多信息,请参见 Section 20.5.3, “Transaction Consistency Guarantees”。

20.1.3.2.1 事务检查

在多主模式下部署组时,会对事务进行检查以确保其与模式兼容。当在多主模式下部署 Group Replication 时,将进行以下严格的一致性检查:

  • 如果在 SERIALIZABLE 隔离级别下执行事务,则在与组同步时,其提交将失败。

  • 如果一个事务针对具有级联约束的外键的表执行,那么当与组进行同步时,其提交将失败。

这些检查由group_replication_enforce_update_everywhere_checks系统变量控制。在多主模式下,该系统变量通常应设置为ON,但可以通过将系统变量设置为OFF来选择性地停用检查。在部署单主模式时,该系统变量必须设置为OFF

20.1.3.2.2 数据定义语句

在多主模式下部署 Group Replication 拓扑时,在执行数据定义语句时,也通常称为数据定义语言(DDL),需要注意。

MySQL 8.0 引入了对原子数据定义语言(DDL)语句的支持,其中完整的 DDL 语句要么作为单个原子事务提交,要么回滚。然而,DDL 语句,无论是否原子,都会隐式结束当前会话中的任何活动事务,就好像在执行该语句之前执行了COMMIT一样。这意味着 DDL 语句不能在另一个事务内执行,在事务控制语句(如START TRANSACTION ... COMMIT)内执行,或者与同一事务内的其他语句组合。

Group Replication 基于一种乐观的复制范式,其中语句会乐观地执行,如果需要则会回滚。每个服务器在未先获得组协议的情况下执行。因此,在多主模式下复制 DDL 语句时需要更加小心。如果对同一对象进行模式更改(使用 DDL)和对对象包含的数据进行更改(使用 DML),则这些更改需要在模式操作尚未完成并在所有地方复制之前通过同一服务器处理。如果未能这样做,当操作被中断或仅部分完成时可能导致数据不一致。如果组部署在单主模式下,则不会出现此问题,因为所有更改都通过同一服务器执行,即主服务器。

有关 MySQL 8.0 中原子 DDL 支持的详细信息,以及某些语句复制行为的变化,请参阅 第 15.1.1 节,“原子数据定义语句支持”。

20.1.3.2.3 版本兼容性

为了获得最佳兼容性和性能,组中的所有成员应该运行相同版本的 MySQL Server,因此也应该运行相同版本的 Group Replication。在多主模式下,这更为重要,因为所有成员通常会以读写模式加入组。如果一个组包含运行不止一个 MySQL Server 版本的成员,那么一些成员可能与其他成员不兼容,因为它们支持其他成员不支持的功能,或者缺少其他成员拥有的功能。为了防范这种情况,在新成员加入时(包括已升级并重新启动的前成员),该成员会对其与组中其他成员的兼容性进行检查。

这些兼容性检查的一个重要结果在多主模式下尤为重要。如果加入的成员运行的 MySQL Server 版本高于现有组成员运行的最低版本,它会加入组但保持为只读模式。(在单主模式下运行的组中,新添加的成员默认为只读模式。)运行 MySQL 8.0.17 或更高版本的成员在检查兼容性时会考虑发布的补丁版本。运行 MySQL 8.0.16 或更低版本,或 MySQL 5.7 的成员只考虑主要版本。

在以多主模式运行的组中,成员使用不同的 MySQL Server 版本,Group Replication 会自动管理运行 MySQL 8.0.17 或更高版本的成员的读写和只读状态。如果一个成员离开组,那些运行当前最低版本的成员会自动设置为读写模式。当您将以单主模式运行的组更改为以多主模式运行时,使用group_replication_switch_to_multi_primary_mode()函数,Group Replication 会自动将成员设置为正确的模式。如果成员运行的 MySQL 服务器版本高于组中最低版本,则会自动将其置于只读模式,而运行最低版本的成员会置于读写模式。

有关组中版本兼容性的完整信息以及在升级过程中如何影响组行为,请参阅第 20.8.1 节,“在组中组合不同的成员版本”。

20.1.4 组复制服务

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-details.html

20.1.4.1 组成员资格

20.1.4.2 失效检测

20.1.4.3 容错性

20.1.4.4 可观察性

本节介绍了组复制构建的一些服务。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-group-membership.html

20.1.4.1 群组成员

在 MySQL Group Replication 中,一组服务器形成一个复制组。群组有一个以 UUID 形式的名称。群组是动态的,服务器可以随时离开(自愿或非自愿)和加入。每当服务器加入或离开时,群组会自动调整自身。

如果一个服务器加入群组,它会通过从现有服务器获取缺失状态来自动更新自身。如果一个服务器离开群组,例如因为维护而关闭,剩余的服务器会注意到它已经离开,并自动重新配置群组。

Group Replication 具有一个群组成员服务,定义了哪些服务器在线并参与群组。在线服务器列表被称为视图。群组中的每个服务器在给定时间点都对哪些服务器是活跃参与群组的成员有一致的视图。

群组成员不仅必须就事务提交达成一致意见,还必须就当前视图达成一致。如果现有成员同意新服务器应该成为群组的一部分,群组将重新配置以将该服务器整合进去,从而触发视图更改。如果一个服务器离开群组,无论是自愿还是非自愿,群组会动态重新排列其配置,并触发视图更改。

当一个成员自愿离开群组时,首先启动动态群重新配置,在此期间,所有成员必须就没有离开的服务器达成新的共识。然而,如果一个成员非自愿离开群组,例如因为意外停止或网络连接中断,它无法启动重新配置。在这种情况下,Group Replication 的故障检测机制在短时间内识别出成员已经离开,并提出了一个没有失败成员的群组重新配置。与自愿离开的成员一样,重新配置需要群组中大多数服务器的同意。然而,如果群组无法达成一致意见,例如因为分区导致没有大多数服务器在线,系统无法动态更改配置,并阻止分裂脑的情况发生。这种情况需要管理员干预。

一个成员可能会短暂离线,然后在故障检测机制检测到其故障之前,尝试重新加入组,而在组被重新配置以移除该成员之前。在这种情况下,重新加入的成员会忘记其先前的状态,但如果其他成员向其发送旨在其崩溃前状态的消息,这可能会导致问题,包括可能的数据不一致性。如果处于这种情况的成员参与 XCom 的共识协议,它有可能导致 XCom 在同一共识轮中传递不同的值,因为在故障前后做出不同的决定。

为了应对这种可能性,在 MySQL 5.7.22 版本和 MySQL 8.0 版本中,Group Replication 会检查这样一种情况:当同一台服务器的新实例尝试加入组时,而其旧实例(具有相同的地址和端口号)仍然被列为成员。新实例将被阻止加入组,直到旧实例通过重新配置被移除。请注意,如果group_replication_member_expel_timeout系统变量添加了等待时间,以允许成员在被驱逐之前重新连接到组,那么受到怀疑的成员在怀疑超时之前重新连接到组,可以作为其当前实例再次活跃在组中。当成员超过驱逐超时并被驱逐出组,或者当服务器上的 Group Replication 被STOP GROUP_REPLICATION语句或服务器故障停止时,它必须作为新实例重新加入。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-failure-detection.html

20.1.4.2 故障检测

Group Replication 的故障检测机制是一个分布式服务,能够识别组中的服务器是否与其他服务器通信,因此被怀疑处于停机状态。如果组的共识是怀疑可能是真实的,组将协调决定将该成员驱逐。驱逐一个不通信的成员是必要的,因为组需要大多数成员就交易或视图更改达成一致。如果一个成员不参与这些决定,组必须将其移除,以增加组中包含大多数正常工作成员的机会,从而可以继续处理交易。

在复制组中,每个成员与其他成员之间都有一条点对点通信通道,形成一个完全连接的图。这些连接由组通信引擎(XCom,一种 Paxos 变体)管理,并使用 TCP/IP 套接字。一个通道用于向成员发送消息,另一个通道用于接收来自成员的消息。如果一个成员在 5 秒内没有收到来自另一个成员的消息,它会怀疑该成员已经失败,并在自己的性能模式表replication_group_members中将该成员的状态列为UNREACHABLE。通常,两个成员会互相怀疑对方已经失败,因为它们彼此之间没有通信。但也有可能,尽管不太可能,成员 A 怀疑成员 B 已经失败,但成员 B 并没有怀疑成员 A 已经失败 - 可能是由于路由或防火墙问题。一个成员也可以怀疑自己。一个与组其他成员隔离的成员怀疑所有其他成员已经失败。

如果一个怀疑持续超过 10 秒,怀疑的成员会试图向组内其他成员传播其观点,即怀疑的成员有缺陷。只有当怀疑的成员是通知者时才会这样做,这是从其内部 XCom 节点编号计算出来的。如果一个成员实际上与组的其他成员隔离开来,它可能会尝试传播其观点,但这不会产生任何后果,因为它无法获得其他成员的多数同意。只有当一个成员是通知者时,怀疑持续时间足够长以传播到组的其他成员,并且其他成员同意时,怀疑才会产生后果。在这种情况下,怀疑的成员被标记为从组中驱逐,在group_replication_member_expel_timeout系统变量设置的等待期过后,驱逐机制检测到并实施驱逐后被驱逐。

在网络不稳定且成员经常在不同组合中失去和重新建立连接的情况下,理论上可能导致一个组标记所有成员进行驱逐,之后该组将停止存在并需要重新设置。为了应对这种可能性,从 MySQL 8.0.20 开始,Group Replication 的 Group Communication System (GCS)跟踪已被标记为驱逐的组成员,并在决定是否存在多数时将其视为被怀疑成员的组。这确保至少有一个成员留在组内,使组能够继续存在。当一个被驱逐的成员实际上已被从组中移除时,GCS 将删除其被标记为驱逐的记录,以便该成员可以重新加入组(如果有可能)。

有关可以配置的 Group Replication 系统变量的信息,以指定工作组成员对故障情况的响应以及被怀疑已经发生故障的组成员采取的行动,请参见 Section 20.7.7, “Responses to Failure Detection and Network Partitioning”。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-fault-tolerance.html

20.1.4.3 容错性

MySQL Group Replication 基于 Paxos 分布式算法的实现,提供服务器之间的分布式协调。因此,它需要大多数服务器处于活动状态才能达成法定人数,从而做出决定。这直接影响系统在不损害自身和整体功能性的情况下能够容忍的故障数量。需要容忍f个故障的服务器数量(n)为n = 2 x f + 1

实际上,这意味着为了容忍一个故障,组内必须有三台服务器。因此,如果一台服务器故障,仍然有两台服务器形成多数(三个中的两个),使系统能够继续自动做出决策并进展。然而,如果第二台服务器非自愿故障,那么组(只剩下一台服务器)将阻塞,因为没有多数达成决定。

以下是一个小表格,说明了上述公式。

组大小 多数 即时容忍的故障数
1 1 0
2 2 0
3 2 1
4 3 1
5 3 2
6 4 2
7 4 3

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-observability.html

20.1.4.4 可观察性

尽管 Group Replication 插件中内置了许多自动化功能,但有时您可能需要了解幕后发生的情况。这就是 Group Replication 和 Performance Schema 的仪表化变得重要的地方。整个系统的状态(包括视图、冲突统计和服务状态)可以通过 Performance Schema 表进行查询。复制协议的分布式性质以及服务器实例之间达成一致并因此在事务和元数据上进行同步使得检查组的状态变得更加简单。例如,您可以连接到组中的单个服务器,并通过在与 Group Replication 相关的 Performance Schema 表上发出 select 语句来获取本地和全局信息。有关更多信息,请参见 第 20.4 节,“监控 Group Replication”。

20.1.5 Group Replication 插件架构

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-plugin-architecture.html

MySQL Group Replication 是一个 MySQL 插件,它建立在现有的 MySQL 复制基础设施之上,利用二进制日志、基于行的日志记录和全局事务标识符等功能。它与当前的 MySQL 框架集成,如性能模式或插件和服务基础设施。以下图表展示了 MySQL Group Replication 的整体架构。

图 20.6 Group Replication 插件块图

图后的文本描述了图表的内容。

MySQL Group Replication 插件包括一组用于捕获、应用和生命周期的 API,控制插件与 MySQL 服务器的交互方式。有接口使信息从服务器流向插件,反之亦然。这些接口将 MySQL 服务器核心与 Group Replication 插件隔离开来,主要是放置在事务执行管道中的钩子。在一个方向上,从服务器到插件,有关于事件的通知,如服务器启动、服务器恢复、服务器准备好接受连接以及服务器即将提交事务。在另一个方向上,插件指示服务器执行动作,如提交或中止正在进行的事务,或将事务排队到中继日志中。

Group Replication 插件架构的下一层是一组组件,当通知路由到它们时会做出反应。捕获组件负责跟踪正在执行的事务相关的上下文。应用程序组件负责在数据库上执行远程事务。恢复组件管理分布式恢复,并负责通过选择捐赠者、管理赶上过程和对捐赠者故障做出反应,使加入组的服务器保持最新。

沿着堆栈继续,复制协议模块包含复制协议的具体逻辑。它处理冲突检测,并接收和传播事务到组中。

Group Replication 插件架构的最后两层是 Group Communication System(GCS)API 和基于 Paxos 的群组通信引擎(XCom)的实现。GCS API 是一个高级 API,抽象出构建复制状态机所需的属性(参见第 20.1 节,“Group Replication 背景”)。因此,它将消息传递层的实现与插件的其余上层分离开来。群组通信引擎处理与复制组成员的通信。

20.2 开始

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-getting-started.html

20.2.1 在单主模式下部署群组复制

20.2.2 本地部署群组复制

MySQL Group Replication 是作为 MySQL 服务器的插件提供的;组中的每个服务器都需要配置和安装插件。本节提供了一个详细的教程,介绍了创建至少三个成员的复制组所需的步骤。

提示

要部署多个 MySQL 实例,您可以使用 InnoDB 集群,它使您能够轻松管理一组 MySQL 服务器实例在 MySQL Shell 中。InnoDB 集群将 MySQL Group Replication 封装在一个编程环境中,使您能够轻松部署一组 MySQL 实例以实现高可用性。此外,InnoDB 集群与 MySQL Router 无缝接口,使您的应用程序能够连接到集群而无需编写自己的故障转移过程。然而,对于不需要高可用性的类似用例,您可以使用 InnoDB ReplicaSet。有关 MySQL Shell 的安装说明,请参阅这里。

20.2.1 在单主模式下部署组复制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-deploying-in-single-primary-mode.html

20.2.1.1 部署用于组复制的实例

20.2.1.2 配置用于组复制的实例

20.2.1.3 分布式恢复的用户凭据

20.2.1.4 启动组复制

20.2.1.5 引导组

20.2.1.6 将实例添加到组中

组中的每个 MySQL 服务器实例可以运行在独立的物理主机上,这是部署组复制的推荐方式。本节解释了如何创建一个由三个 MySQL Server 实例组成的复制组,每个实例运行在不同的主机上。有关在同一主机上部署运行组复制的多个 MySQL 服务器实例的信息,请参见第 20.2.2 节,“在本地部署组复制”,例如用于测试目的。

图 20.7 组架构

三个服务器实例,S1、S2 和 S3,作为一个互联的组部署,并且客户端与每个服务器实例通信。

本教程解释了如何获取并部署带有组复制插件的 MySQL Server,如何在创建组之前配置每个服务器实例,以及如何使用性能模式监视来验证一切是否正常运行。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-deploying-instances.html

20.2.1.1 部署用于组复制的实例

第一步是部署至少三个 MySQL Server 实例,此过程演示了在多个主机上使用实例的方法,命名为 s1、s2 和 s3。假设每个主机上都安装了 MySQL Server(参见 Chapter 2, Installing MySQL)。MySQL Server 8.0 提供了 Group Replication 插件;不需要额外的软件,但插件必须安装在运行中的 MySQL 服务器上。请参见 Section 20.2.1.1, “Deploying Instances for Group Replication”;更多信息,请参见 Section 7.6, “MySQL Server Plugins”。

在这个示例中,使用了三个实例来组成一个组,这是创建组的最小实例数。增加更多实例可以增加组的容错能力。例如,如果组由三个成员组成,在一个实例故障的情况下,组可以继续运行。但在另一个实例故障的情况下,组将无法继续处理写事务。通过增加更多实例,组在继续处理事务的同时可以容忍更多服务器的故障。可以在一个组中使用的最大实例数为九。更多信息请参见 Section 20.1.4.2, “Failure Detection”。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-instances.html

20.2.1.2 为 Group Replication 配置实例

本节解释了要为用于 Group Replication 的 MySQL Server 实例配置的配置设置。有关背景信息,请参阅 Section 20.3, “Requirements and Limitations”。

  • 存储引擎

  • 复制框架

  • Group Replication 设置

存储引擎

对于 Group Replication,数据必须存储在 InnoDB 事务性存储引擎中(详情请参阅 Section 20.3.1, “Group Replication Requirements”)。使用其他存储引擎,包括临时的 MEMORY 存储引擎,可能会导致 Group Replication 中的错误。请设置 disabled_storage_engines 系统变量如下以防止其使用:

disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"

请注意,当禁用 MyISAM 存储引擎时,当您将 MySQL 实例升级到仍在使用 mysql_upgrade 的版本(在 MySQL 8.0.16 之前),mysql_upgrade 可能会失败并显示错误。为了处理这个问题,您可以在运行 mysql_upgrade 时重新启用该存储引擎,然后在重新启动服务器时再次禁用它。更多信息,请参阅 Section 6.4.5, “mysql_upgrade — Check and Upgrade MySQL Tables”。

复制框架

以下设置根据 MySQL Group Replication 的要求配置复制。

server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON

这些设置配置服务器使用唯一标识号 1,启用 Section 19.1.3, “Replication with Global Transaction Identifiers”,并且只允许执行可以安全记录使用 GTID 的语句。

在 MySQL 8.0.20 及更早版本中,还需要以下设置:

binlog_checksum=NONE

此设置禁用写入二进制日志的事件的校验和,默认情况下为启用状态。从 MySQL 8.0.21 开始,组复制支持二进制日志中的校验和,并可以使用它们来验证某些通道上事件的完整性,因此您可以使用默认设置。有关更多详细信息,请参见第 20.3.2 节,“组复制限制”。

如果您使用的是早于 8.0.3 的 MySQL 版本,在该版本中改进了复制的默认值,您还需要将这些行添加到成员的选项文件中。如果在后续版本的选项文件中有这些系统变量之一,请确保它们设置如下所示。有关更多详细信息,请参见第 20.3.1 节,“组复制要求”。

log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE
transaction_write_set_extraction=XXHASH64
组复制设置

此时,选项文件确保服务器已配置并被指示在给定配置下实例化复制基础设施。以下部分为服务器配置组复制设置。

plugin_load_add='group_replication.so'
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
group_replication_local_address= "s1:33061"
group_replication_group_seeds= "s1:33061,s2:33061,s3:33061"
group_replication_bootstrap_group=off
  • plugin-load-add将组复制插件添加到服务器在启动时加载的插件列表中。在生产部署中,这比手动安装插件更可取。

  • 配置group_replication_group_name告诉插件,它正在加入或创建的组名为"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"。

    group_replication_group_name的值必须是有效的 UUID。您可以使用SELECT UUID()来生成一个。此 UUID 是 GTID 的一部分,当来自客户端的事务被组成员接收,并且由组成员内部生成的视图更改事件被写入二进制日志时使用。

  • group_replication_start_on_boot变量配置为off会指示插件在服务器启动时不自动启动操作。在设置组复制时很重要,因为这样可以确保您在手动启动插件之前可以配置服务器。一旦成员配置完成,您可以将group_replication_start_on_boot设置为on,这样组复制将在服务器启动时自动启动。

  • 配置group_replication_local_address设置成员用于与组内其他成员进行内部通信的网络地址和端口。组复制使用此地址进行涉及组通信引擎(XCom,一种 Paxos 变体)的远程实例的内部成员之间连接。

    重要

    组复制本地地址必须与用于 SQL 客户端连接的主机名和端口不同,这些由 MySQL 服务器的hostnameport系统变量定义。它不能用于客户端应用程序。它只能用于运行组复制时组成员之间的内部通信。

    group_replication_local_address配置的网络地址必须由所有组成员解析。例如,如果每个服务器实例位于具有固定网络地址的不同机器上,你可以使用机器的 IP 地址,例如 10.0.0.1。如果使用主机名,必须使用完全限定名称,并确保通过 DNS、正确配置的/etc/hosts文件或其他名称解析过程解析。从 MySQL 8.0.14 开始,IPv6 地址(或解析为其的主机名)也可以使用,以及 IPv4 地址。一个组可以包含使用 IPv6 和使用 IPv4 的成员的混合。有关组复制对 IPv6 网络的支持以及混合 IPv4 和 IPv6 组的更多信息,请参阅第 20.5.5 节,“IPv6 和混合 IPv6 和 IPv4 组的支持”。

    推荐的group_replication_local_address端口是 33061。group_replication_local_address被组复制用作复制组内组成员的唯一标识符。只要主机名或 IP 地址都不同,你可以为所有复制组成员使用相同的端口,就像在本教程中演示的那样。或者,只要端口都不同,你可以为所有成员使用相同的主机名或 IP 地址,例如在第 20.2.2 节,“本地部署组复制”中所示。

    现有成员为组复制的分布式恢复过程提供给加入成员的连接,并非由group_replication_local_address配置的网络地址。在 MySQL 8.0.20 之前,组成员为分布式恢复提供其标准 SQL 客户端连接给加入成员,由 MySQL 服务器的hostnameport系统变量指定。从 MySQL 8.0.21 开始,组成员可以为加入成员提供一组专用客户端连接作为分布式恢复的备用端点。更多详情,请参阅第 20.5.4.1 节,“分布式恢复的连接”。

    重要

    如果加入成员无法正确使用由 MySQL 服务器的hostname系统变量定义的主机名来识别其他成员,分布式恢复可能会失败。建议运行 MySQL 的操作系统具有经过正确配置的唯一主机名,可以使用 DNS 或本地设置。服务器用于 SQL 客户端连接的主机名可以在性能模式表replication_group_membersMember_host列中验证。如果多个组成员外部化了操作系统设置的默认主机名,加入成员可能无法将其解析为正确的成员地址,无法连接进行分布式恢复。在这种情况下,您可以使用 MySQL 服务器的report_host系统变量为每个服务器配置一个唯一的主机名来外部化。

  • 配置group_replication_group_seeds设置了组成员的主机名和端口,新成员使用这些信息来建立与组的连接。这些成员被称为种子成员。一旦连接建立,组成员信息将列在性能模式表replication_group_members中。通常group_replication_group_seeds列表包含每个组成员的group_replication_local_addresshostname:port,但这并非强制,可以选择一部分组成员作为种子。

    重要

    group_replication_group_seeds中列出的hostname:port是种子成员的内部网络地址,由group_replication_local_address配置,而不是用于 SQL 客户端连接的hostname:port,例如在性能模式表replication_group_members中显示。

    启动组的服务器不使用此选项,因为它是初始服务器,负责引导组。换句话说,启动组的服务器上存在的任何数据都将用作下一个加入成员的数据。第二个加入的服务器请求组内唯一的成员加入,第二个服务器上缺失的数据将从引导成员的捐赠数据中复制,然后组扩展。第三个加入的服务器可以请求其中任何两个加入,数据将同步到新成员,然后组再次扩展。后续服务器加入时重复此过程。

    警告

    当同时加入多个服务器时,请确保它们指向已经在组内的种子成员。不要使用正在加入组的成员作为种子,因为当联系时它们可能尚未加入组。

    最好的做法是首先启动引导成员,并让它创建组。然后将其设置为其余加入成员的种子成员。这样确保在加入其余成员时已经形成了一个组。

    不支持同时创建组并加入多个成员。这样做可能会成功,但有可能操作竞争,然后加入组的操作最终会出现错误或超时。

    加入成员必须使用种子成员在group_replication_group_seeds选项中广告的相同协议(IPv4 或 IPv6)与种子成员通信。为了 Group Replication 的 IP 地址权限,种子成员的允许列表必须包含加入成员的 IP 地址,以供种子成员提供的协议使用,或者解析为该协议的地址的主机名。如果加入成员的协议与种子成员广告的协议不匹配,则必须设置并允许此地址或主机名,以及加入成员的group_replication_local_address。如果加入成员没有适当协议的允许地址,则其连接尝试将被拒绝。有关更多信息,请参见 Section 20.6.4, “Group Replication IP Address Permissions”。

  • 配置group_replication_bootstrap_group指示插件是否引导组。在这种情况下,即使s1是组的第一个成员,我们在选项文件中将此变量设置为关闭。相反,我们在实例运行时配置group_replication_bootstrap_group,以确保只有一个成员实际引导组。

    重要

    group_replication_bootstrap_group变量必须在任何时候仅在属于组的一个服务器实例上启用,通常是您引导组的第一次(或者整个组被关闭并重新启动的情况下)。如果多次引导组,例如当多个服务器实例设置了此选项时,则可能会创建人为的脑裂情况,即存在具有相同名称的两个不同组。始终在第一个服务器实例上线后设置group_replication_bootstrap_group=off

本教程中描述的系统变量是启动新成员所需的配置设置,但还有其他系统变量可用于配置组成员。这些列在 Section 20.9, “Group Replication Variables”中。

重要

一些系统变量,有些是特定于组复制,有些不是,都是组范围的配置设置,必须在所有组成员上具有相同的值。如果组成员为其中一个这些系统变量设置了值,并且加入的成员为其设置了不同的值,则加入的成员无法加入组,并返回错误消息。如果组成员为此系统变量设置了值,而加入的成员不支持该系统变量,则无法加入组。所有这些系统变量都在第 20.9 节,“组复制变量”中标识。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-user-credentials.html

20.2.1.3 分布式恢复的用户凭据

组复制使用分布式恢复过程在加入组时同步组成员。分布式恢复涉及将捐赠者的二进制日志中的事务传输到加入成员,使用名为group_replication_recovery的复制通道。因此,您必须设置具有正确权限的复制用户,以便组复制可以建立直接成员之间的复制通道。如果组成员已设置为支持远程克隆操作作为分布式恢复的一部分,该操作从 MySQL 8.0.17 开始提供,那么此复制用户也用作捐赠者上的克隆用户,并且对于此角色也需要正确的权限。有关分布式恢复的完整描述,请参见第 20.5.4 节,“分布式恢复”。

每个组成员上的分布式恢复必须使用相同的复制用户。可以在二进制日志中记录为分布式恢复创建复制用户的过程,然后依靠分布式恢复来复制用于创建用户的语句。或者,您可以在创建复制用户之前禁用二进制日志记录,然后在每个成员上手动创建用户,例如,如果您想避免更改传播到其他服务器实例。如果这样做,请确保在配置用户后重新启用二进制日志记录。

重要提示

如果您的组的分布式恢复连接使用 SSL,那么在加入成员连接到捐赠者之前,必须在每台服务器上创建复制用户。有关为分布式恢复连接设置 SSL 并创建需要 SSL 的复制用户的说明,请参见第 20.6.3 节,“保护分布式恢复连接”

重要提示

默认情况下,在 MySQL 8 中创建的用户使用第 8.4.1.2 节,“缓存 SHA-2 可插拔认证”。如果用于分布式恢复的复制用户使用缓存 SHA-2 认证插件,并且在分布式恢复连接中使用 SSL,那么 RSA 密钥对用于密码交换。您可以将复制用户的公钥复制到加入成员,或者在请求时配置捐赠者提供公钥。有关如何执行此操作的说明,请参见第 20.6.3.1 节,“分布式恢复的安全用户凭据”。

要为分布式恢复创建复制用户,请按照以下步骤进行:

  1. 启动 MySQL 服务器实例,然后连接客户端。

  2. 如果要禁用二进制日志记录,以便在每个实例上单独创建复制用户,请执行以下语句:

    mysql> SET SQL_LOG_BIN=0;
    
  3. 创建一个具有以下权限的 MySQL 用户:

    • REPLICATION SLAVE,用于与捐赠者建立分布式恢复连接以检索数据。

    • CONNECTION_ADMIN,确保如果涉及的服务器之一被置于脱机模式,则不会终止 Group Replication 连接。

    • BACKUP_ADMIN,如果复制组中的服务器已设置为支持克隆(参见 Section 20.5.4.2, “Cloning for Distributed Recovery”)。此权限在分布式恢复的克隆操作中,需要成员作为捐赠者时才需要。

    • GROUP_REPLICATION_STREAM,如果 MySQL 通信堆栈用于复制组(参见 Section 20.6.1, “Communication Stack for Connection Security Management”)。此权限要求用户帐户能够使用 MySQL 通信堆栈建立和维护 Group Replication 的连接。

    在此示例中显示了用户rpl_user和密码password。在配置服务器时,请使用适当的用户名和密码:

    mysql> CREATE USER *rpl_user*@'%' IDENTIFIED BY '*password*';
    mysql> GRANT REPLICATION SLAVE ON *.* TO *rpl_user*@'%';
    mysql> GRANT CONNECTION_ADMIN ON *.* TO *rpl_user*@'%';
    mysql> GRANT BACKUP_ADMIN ON *.* TO *rpl_user*@'%';
    mysql> GRANT GROUP_REPLICATION_STREAM ON *.* TO *rpl_user*@'%';
    mysql> FLUSH PRIVILEGES;
    
  4. 如果您禁用了二进制日志记录,请在创建用户后立即通过以下语句启用它:

    mysql> SET SQL_LOG_BIN=1;
    
  5. 创建复制用户后,必须向服务器提供用户凭据,以供分布式恢复使用。您可以通过将用户凭据设置为group_replication_recovery通道的凭据,使用CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(MySQL 8.0.23 之前)。或者,从 MySQL 8.0.21 开始,您可以在START GROUP_REPLICATION语句中指定分布式恢复的用户凭据。

    • 使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO设置的用户凭据以明文形式存储在服务器上的复制元数据存储库中。它们在启动 Group Replication 时应用,包括如果group_replication_start_on_boot系统变量设置为ON时的自动启动。

    • START GROUP_REPLICATION中指定的用户凭据仅保存在内存中,并且通过STOP GROUP_REPLICATION语句或服务器关闭时会被删除。您必须发出START GROUP_REPLICATION语句再次提供凭据,因此不能使用这些凭据自动启动 Group Replication。通过指定用户凭据的这种方法有助于保护 Group Replication 服务器免受未经授权的访问。

    有关使用每种提供用户凭据方法的安全影响的更多信息,请参阅 Section 20.6.3.1.3, “提供复制用户凭据的安全性”。如果选择使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句提供用户凭据,请立即在服务器实例上发出以下语句,将rpl_userpassword替换为创建用户时使用的值:

    mysql> CHANGE MASTER TO MASTER_USER='*rpl_user*', MASTER_PASSWORD='*password*' \\
    		      FOR CHANNEL 'group_replication_recovery';
    
    Or from MySQL 8.0.23:
    mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='*rpl_user*', SOURCE_PASSWORD='*password*' \\
    		      FOR CHANNEL 'group_replication_recovery';
    

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-launching.html

20.2.1.4 启动 Group Replication

首先需要确保在服务器 s1 上安装了 Group Replication 插件。如果在选项文件中使用了 plugin_load_add='group_replication.so',那么 Group Replication 插件已经安装好了,您可以继续下一步操作。否则,您必须手动安装该插件;要做到这一点,使用 mysql 客户端连接到服务器,并执行这里显示的 SQL 语句:

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';

重要提示

在加载 Group Replication 之前,mysql.session 用户必须存在。mysql.session 是在 MySQL 版本 8.0.2 中添加的。如果您的数据字典是使用早期版本初始化的,则必须执行 MySQL 升级过程(参见 第三章,升级 MySQL)。如果未运行升级,则 Group Replication 在启动时会出现错误消息,指出尝试使用用户 mysql.session@localhost 访问服务器时出错。确保用户存在于服务器中,并且在服务器更新后运行了 mysql_upgrade。

要检查插件是否成功安装,请执行 SHOW PLUGINS; 并检查输出。应该显示类似于以下内容:

mysql> SHOW PLUGINS;
+----------------------------+----------+--------------------+----------------------+-------------+
| Name                       | Status   | Type               | Library              | License     |
+----------------------------+----------+--------------------+----------------------+-------------+
| binlog                     | ACTIVE   | STORAGE ENGINE     | NULL                 | PROPRIETARY |

(...)

| group_replication          | ACTIVE   | GROUP REPLICATION  | group_replication.so | PROPRIETARY |
+----------------------------+----------+--------------------+----------------------+-------------+

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-bootstrap.html

20.2.1.5 引导组

首次启动组的过程称为引导。您使用group_replication_bootstrap_group系统变量来引导一个组。引导应该只由单个服务器执行,即启动组的服务器,并且只执行一次。这就是为什么group_replication_bootstrap_group选项的值未存储在实例的选项文件中。如果它保存在选项文件中,在重新启动时,服务器会自动用相同名称引导第二个组。这将导致具有相同名称的两个不同组。相同的推理适用于设置为ON时停止和重新启动插件。因此,为了安全地引导组,请连接到 s1 并执行以下语句:

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

或者,如果您正在为分布式恢复提供用户凭据START GROUP_REPLICATION语句(从 MySQL 8.0.21 开始),请执行以下语句:

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION USER='*rpl_user*', PASSWORD='*password*';
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

一旦START GROUP_REPLICATION语句返回,组已经启动。您可以检查组现在是否已创建,并且其中有一个成员:

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE  | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
| group_replication_applier | ce9be252-2b71-11e6-b8f4-00212844f856 |   s1        |       3306  | ONLINE        |             |                | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
1 row in set (0.0108 sec)

这个表中的信息确认了组中有一个具有唯一标识符ce9be252-2b71-11e6-b8f4-00212844f856的成员,它处于ONLINE状态,并在端口3306上的s1上监听客户端连接。

用于演示服务器确实处于组中并且能够处理负载的目的,创建一个表并向其中添加一些内容。

mysql> CREATE DATABASE test;
mysql> USE test;
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
mysql> INSERT INTO t1 VALUES (1, 'Luis');

检查表t1的内容和二进制日志。

mysql> SELECT * FROM t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+

mysql> SHOW BINLOG EVENTS;
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name      | Pos | Event_type     | Server_id | End_log_pos | Info                                                               |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| binlog.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 8.0.36-log, Binlog ver: 4                              |
| binlog.000001 | 123 | Previous_gtids |         1 |         150 |                                                                    |
| binlog.000001 | 150 | Gtid           |         1 |         211 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1'  |
| binlog.000001 | 211 | Query          |         1 |         270 | BEGIN                                                              |
| binlog.000001 | 270 | View_change    |         1 |         369 | view_id=14724817264259180:1                                        |
| binlog.000001 | 369 | Query          |         1 |         434 | COMMIT                                                             |
| binlog.000001 | 434 | Gtid           |         1 |         495 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2'  |
| binlog.000001 | 495 | Query          |         1 |         585 | CREATE DATABASE test                                               |
| binlog.000001 | 585 | Gtid           |         1 |         646 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:3'  |
| binlog.000001 | 646 | Query          |         1 |         770 | use `test`; CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL) |
| binlog.000001 | 770 | Gtid           |         1 |         831 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:4'  |
| binlog.000001 | 831 | Query          |         1 |         899 | BEGIN                                                              |
| binlog.000001 | 899 | Table_map      |         1 |         942 | table_id: 108 (test.t1)                                            |
| binlog.000001 | 942 | Write_rows     |         1 |         984 | table_id: 108 flags: STMT_END_F                                    |
| binlog.000001 | 984 | Xid            |         1 |        1011 | COMMIT /* xid=38 */                                                |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+

如上所示,数据库和表对象已创建,并且它们对应的 DDL 语句已写入二进制日志。此外,数据已插入到表中并写入二进制日志,因此可以通过从捐赠者的二进制日志进行状态传输来用于分布式恢复。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-adding-instances.html

20.2.1.6 向组中添加实例

此时,组中有一个成员,服务器 s1,其中包含一些数据。现在是扩展组的时候了,通过添加之前配置的其他两台服务器。

20.2.1.6.1 添加第二个实例

要添加第二个实例,服务器 s2,首先为其创建配置文件。配置与用于服务器 s1 的配置类似,除了诸如server_id之类的内容。以下列出了不同的行。

[mysqld]

#
# Disable other storage engines
#
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"

#
# Replication configuration parameters
#
server_id=2
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE # Not needed from 8.0.21

#
# Group Replication configuration
#
plugin_load_add='group_replication.so'
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
group_replication_local_address= "s2:33061"
group_replication_group_seeds= "s1:33061,s2:33061,s3:33061"
group_replication_bootstrap_group= off

与为服务器 s1 执行的过程类似,放置选项文件后启动服务器。然后按以下方式配置分布式恢复凭据。这些命令与在设置服务器 s1 时使用的命令相同,因为用户在组内共享。此成员需要在第 20.2.1.3 节,“分布式恢复的用户凭据”中配置相同的复制用户。如果您依赖分布式恢复来在所有成员上配置用户,则当 s2 连接到种子 s1 时,复制用户将被复制或克隆到 s1。如果在配置用户凭据时未启用二进制日志记录,并且不使用远程克隆操作进行状态传输,则必须在 s2 上创建复制用户。在这种情况下,连接到 s2 并发出:

SET SQL_LOG_BIN=0;
CREATE USER *rpl_user*@'%' IDENTIFIED BY '*password*';
GRANT REPLICATION SLAVE ON *.* TO *rpl_user*@'%';
GRANT CONNECTION_ADMIN ON *.* TO *rpl_user*@'%';
GRANT BACKUP_ADMIN ON *.* TO *rpl_user*@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO *rpl_user*@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;

如果您正在使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句提供用户凭据,请在此之后发出以下语句:

CHANGE MASTER TO MASTER_USER='*rpl_user*', MASTER_PASSWORD='*password*' \\
	FOR CHANNEL 'group_replication_recovery';

Or from MySQL 8.0.23:
CHANGE REPLICATION SOURCE TO SOURCE_USER='*rpl_user*', SOURCE_PASSWORD='*password*' \\
	FOR CHANNEL 'group_replication_recovery';

提示

如果您正在使用缓存的 SHA-2 身份验证插件,这是 MySQL 8 中的默认设置,请参阅第 20.6.3.1.1 节,“具有缓存 SHA-2 身份验证插件的复制用户”。

如有必要,安装组复制插件,请参阅第 20.2.1.4 节,“启动组复制”。

启动组复制,s2 开始加入组的过程。

mysql> START GROUP_REPLICATION;

或者,如果您正在为START GROUP_REPLICATION语句提供分布式恢复的用户凭据(从 MySQL 8.0.21 开始):

mysql> START GROUP_REPLICATION USER='*rpl_user*', PASSWORD='*password*';

与在 s1 上执行的先前步骤不同,这里的区别在于您需要引导组,因为组已经存在。换句话说,在 s2 上 group_replication_bootstrap_group 设置为OFF,并且在启动 Group Replication 之前不需要发出SET GLOBAL group_replication_bootstrap_group=ON;,因为组已经由服务器 s1 创建和引导。此时,服务器 s2 只需要添加到已经存在的组中。

提示

当 Group Replication 成功启动并且服务器加入组时,它会检查 super_read_only 变量。通过在成员的配置文件中将 super_read_only 设置为 ON,您可以确保由于任何原因在启动 Group Replication 时失败的服务器不接受事务。如果服务器应该作为读写实例加入组,例如作为单主组中的主服务器或作为多主组的成员,当 super_read_only 变量设置为 ON 时,加入组时它会被设置为 OFF。

再次检查 performance_schema.replication_group_members 表,显示组中现在有两个ONLINE服务器。

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 395409e1-6dfa-11e6-970b-00212844f856 |   s1        |        3306 | ONLINE       | PRIMARY     | 8.0.27         | XCom                       |
| group_replication_applier | ac39f1e6-6dfa-11e6-a69d-00212844f856 |   s2        |        3306 | ONLINE       | SECONDARY   | 8.0.27         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+

当 s2 尝试加入组时,第 20.5.4 节,“分布式恢复” 确保 s2 应用了与 s1 应用的相同事务。一旦此过程完成,s2 可以作为成员加入组,并在此时标记为ONLINE。换句话说,它必须已经自动赶上了服务器 s1。一旦 s2 处于ONLINE状态,它就开始与组处理事务。验证 s2 是否已经与服务器 s1 同步如下。

mysql> SHOW DATABASES LIKE 'test';
+-----------------+
| Database (test) |
+-----------------+
| test            |
+-----------------+

mysql> SELECT * FROM test.t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+

mysql> SHOW BINLOG EVENTS;
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name      | Pos  | Event_type     | Server_id | End_log_pos | Info                                                               |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| binlog.000001 |    4 | Format_desc    |         2 |         123 | Server ver: 8.0.36-log, Binlog ver: 4                              |
| binlog.000001 |  123 | Previous_gtids |         2 |         150 |                                                                    |
| binlog.000001 |  150 | Gtid           |         1 |         211 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1'  |
| binlog.000001 |  211 | Query          |         1 |         270 | BEGIN                                                              |
| binlog.000001 |  270 | View_change    |         1 |         369 | view_id=14724832985483517:1                                        |
| binlog.000001 |  369 | Query          |         1 |         434 | COMMIT                                                             |
| binlog.000001 |  434 | Gtid           |         1 |         495 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2'  |
| binlog.000001 |  495 | Query          |         1 |         585 | CREATE DATABASE test                                               |
| binlog.000001 |  585 | Gtid           |         1 |         646 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:3'  |
| binlog.000001 |  646 | Query          |         1 |         770 | use `test`; CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL) |
| binlog.000001 |  770 | Gtid           |         1 |         831 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:4'  |
| binlog.000001 |  831 | Query          |         1 |         890 | BEGIN                                                              |
| binlog.000001 |  890 | Table_map      |         1 |         933 | table_id: 108 (test.t1)                                            |
| binlog.000001 |  933 | Write_rows     |         1 |         975 | table_id: 108 flags: STMT_END_F                                    |
| binlog.000001 |  975 | Xid            |         1 |        1002 | COMMIT /* xid=30 */                                                |
| binlog.000001 | 1002 | Gtid           |         1 |        1063 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:5'  |
| binlog.000001 | 1063 | Query          |         1 |        1122 | BEGIN                                                              |
| binlog.000001 | 1122 | View_change    |         1 |        1261 | view_id=14724832985483517:2                                        |
| binlog.000001 | 1261 | Query          |         1 |        1326 | COMMIT                                                             |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+

如上所示,第二个服务器已添加到组中,并且已自动复制了来自服务器 s1 的更改。换句话说,应用在 s1 上直到 s2 加入组的时间点的事务已经复制到 s2。

20.2.1.6.2 添加额外实例

将额外的实例添加到组中本质上与添加第二个服务器的步骤相同,只是配置必须像对服务器 s2 进行配置一样进行更改。总结所需的命令如下:

  1. 创建配置文件。

    [mysqld]
    
    #
    # Disable other storage engines
    #
    disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
    
    #
    # Replication configuration parameters
    #
    server_id=3
    gtid_mode=ON
    enforce_gtid_consistency=ON
    binlog_checksum=NONE # Not needed from 8.0.21
    
    #
    # Group Replication configuration
    #
    plugin_load_add='group_replication.so'
    group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
    group_replication_start_on_boot=off
    group_replication_local_address= "s3:33061"
    group_replication_group_seeds= "s1:33061,s2:33061,s3:33061"
    group_replication_bootstrap_group= off
    
  2. 启动服务器并连接到它。为分布式恢复创建复制用户。

    SET SQL_LOG_BIN=0;
    CREATE USER *rpl_user*@'%' IDENTIFIED BY '*password*';
    GRANT REPLICATION SLAVE ON *.* TO *rpl_user*@'%';
    GRANT CONNECTION_ADMIN ON *.* TO *rpl_user*@'%';
    GRANT BACKUP_ADMIN ON *.* TO *rpl_user*@'%';
    GRANT GROUP_REPLICATION_STREAM ON *.* TO *rpl_user*@'%';
    FLUSH PRIVILEGES;
    SET SQL_LOG_BIN=1;
    

    如果您正在使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句提供用户凭据,请在此之后发出以下语句:

    CHANGE MASTER TO MASTER_USER='*rpl_user*', MASTER_PASSWORD='*password*' \\
    	FOR CHANNEL 'group_replication_recovery';
    
    Or from MySQL 8.0.23:
    CHANGE REPLICATION SOURCE TO SOURCE_USER='*rpl_user*', SOURCE_PASSWORD='*password*' \\
    	FOR CHANNEL 'group_replication_recovery';
    
  3. 如有必要,安装组复制插件。

    INSTALL PLUGIN group_replication SONAME 'group_replication.so';
    
  4. 启动组复制。

    mysql> START GROUP_REPLICATION;
    

    或者,如果您正在为分布式恢复提供用户凭据,可以在START GROUP_REPLICATION语句中执行此操作(从 MySQL 8.0.21 开始):

    mysql> START GROUP_REPLICATION USER='*rpl_user*', PASSWORD='*password*';
    

此时服务器 s3 已经启动并运行,已加入组并赶上了组内其他服务器的进度。再次查看performance_schema.replication_group_members表可以确认这一点。

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 395409e1-6dfa-11e6-970b-00212844f856 |   s1        |        3306 | ONLINE       | PRIMARY     | 8.0.27         | XCom                       |
| group_replication_applier | 7eb217ff-6df3-11e6-966c-00212844f856 |   s3        |        3306 | ONLINE       | SECONDARY   | 8.0.27         | XCom                       |
| group_replication_applier | ac39f1e6-6dfa-11e6-a69d-00212844f856 |   s2        |        3306 | ONLINE       | SECONDARY   | 8.0.27         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+

在服务器 s2 或服务器 s1 上发出相同的查询会得到相同的结果。此外,您可以验证服务器 s3 已经赶上:

mysql> SHOW DATABASES LIKE 'test';
+-----------------+
| Database (test) |
+-----------------+
| test            |
+-----------------+

mysql> SELECT * FROM test.t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+

mysql> SHOW BINLOG EVENTS;
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name      | Pos  | Event_type     | Server_id | End_log_pos | Info                                                               |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| binlog.000001 |    4 | Format_desc    |         3 |         123 | Server ver: 8.0.36-log, Binlog ver: 4                              |
| binlog.000001 |  123 | Previous_gtids |         3 |         150 |                                                                    |
| binlog.000001 |  150 | Gtid           |         1 |         211 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1'  |
| binlog.000001 |  211 | Query          |         1 |         270 | BEGIN                                                              |
| binlog.000001 |  270 | View_change    |         1 |         369 | view_id=14724832985483517:1                                        |
| binlog.000001 |  369 | Query          |         1 |         434 | COMMIT                                                             |
| binlog.000001 |  434 | Gtid           |         1 |         495 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2'  |
| binlog.000001 |  495 | Query          |         1 |         585 | CREATE DATABASE test                                               |
| binlog.000001 |  585 | Gtid           |         1 |         646 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:3'  |
| binlog.000001 |  646 | Query          |         1 |         770 | use `test`; CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL) |
| binlog.000001 |  770 | Gtid           |         1 |         831 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:4'  |
| binlog.000001 |  831 | Query          |         1 |         890 | BEGIN                                                              |
| binlog.000001 |  890 | Table_map      |         1 |         933 | table_id: 108 (test.t1)                                            |
| binlog.000001 |  933 | Write_rows     |         1 |         975 | table_id: 108 flags: STMT_END_F                                    |
| binlog.000001 |  975 | Xid            |         1 |        1002 | COMMIT /* xid=29 */                                                |
| binlog.000001 | 1002 | Gtid           |         1 |        1063 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:5'  |
| binlog.000001 | 1063 | Query          |         1 |        1122 | BEGIN                                                              |
| binlog.000001 | 1122 | View_change    |         1 |        1261 | view_id=14724832985483517:2                                        |
| binlog.000001 | 1261 | Query          |         1 |        1326 | COMMIT                                                             |
| binlog.000001 | 1326 | Gtid           |         1 |        1387 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:6'  |
| binlog.000001 | 1387 | Query          |         1 |        1446 | BEGIN                                                              |
| binlog.000001 | 1446 | View_change    |         1 |        1585 | view_id=14724832985483517:3                                        |
| binlog.000001 | 1585 | Query          |         1 |        1650 | COMMIT                                                             |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+

20.2.2 本地部署组复制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-deploying-locally.html

部署组复制最常见的方式是使用多个服务器实例,以提供高可用性。也可以在本地部署组复制,例如用于测试目的。本节解释了如何在本地部署组复制。

重要

组复制通常部署在多个主机上,因为这样可以提供高可用性。本节中的说明不适用于生产部署,因为所有 MySQL 服务器实例都在同一台主机上运行。如果此主机发生故障,整个组都会失败。因此,此信息应仅用于测试目的,不应在生产环境中使用。

本节解释了如何在一台物理机器上创建一个包含三个 MySQL 服务器实例的复制组。这意味着需要三个数据目录,每个服务器实例一个,并且需要独立配置每个实例。此过程假定 MySQL 服务器已下载并解压缩到名为mysql-8.0的目录中。每个 MySQL 服务器实例都需要一个特定的数据目录。创建一个名为data的目录,然后在该目录中为每个服务器实例创建一个子目录,例如s1s2s3,并对每个实例进行初始化。

mysql-8.0/bin/mysqld --initialize-insecure --basedir=$PWD/mysql-8.0 --datadir=$PWD/data/s1
mysql-8.0/bin/mysqld --initialize-insecure --basedir=$PWD/mysql-8.0 --datadir=$PWD/data/s2
mysql-8.0/bin/mysqld --initialize-insecure --basedir=$PWD/mysql-8.0 --datadir=$PWD/data/s3

data/s1data/s2data/s3中是一个已初始化的数据目录,包含 mysql 系统数据库和相关表等等。要了解更多关于初始化过程的信息,请参见第 2.9.1 节,“初始化数据目录”。

警告

在生产环境中不要使用-initialize-insecure,这只是为了简化教程而使用的。有关安全设置的更多信息,请参见第 20.6 节,“组复制安全”。

本地组复制成员的配置

当您按照第 20.2.1.2 节,“为组复制配置实例”时,您需要为前一节添加的数据目录添加配置。例如:

[mysqld]

# server configuration
datadir=<full_path_to_data>/data/s1
basedir=<full_path_to_bin>/mysql-8.0/

port=24801
socket=<full_path_to_sock_dir>/s1.sock

这些设置配置了 MySQL 服务器使用之前创建的数据目录以及服务器应该打开和开始监听传入连接的端口。

注意

本教程中使用非默认端口 24801,因为三个服务器实例使用相同的主机名。在三台不同机器的设置中,这是不需要的。

组复制需要成员之间的网络连接,这意味着每个成员必须能够解析所有其他成员的网络地址。例如,在本教程中,所有三个实例都在一台机器上运行,因此为了确保成员之间可以联系,您可以在选项文件中添加一行,例如report_host=127.0.0.1

然后,每个成员需要能够连接到其他成员的group_replication_local_address。例如,在成员 s1 的选项文件中添加:

group_replication_local_address= "127.0.0.1:24901"
group_replication_group_seeds= "127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903"

这将配置 s1 使用端口 24901 进行与种子成员的内部组通信。对于要添加到组中的每个服务器实例,请在成员的选项文件中进行这些更改。对于每个成员,您必须确保指定了唯一地址,因此对于group_replication_local_address,每个实例使用唯一端口。通常,您希望所有成员都能够作为加入组并且尚未通过组处理事务的成员的种子,因此,请像上面显示的那样将所有端口添加到group_replication_group_seeds

第 20.2.1 节,“在单主模式下部署组复制”的其余步骤同样适用于您以这种方式在本地部署的组。

20.3 需求和限制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-requirements-and-limitations.html

20.3.1 集群复制需求

20.3.2 集群复制限制

本节列出并解释了集群复制的需求和限制。

20.3.1 Group Replication Requirements

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-requirements.html

  • 基础设施

  • 服务器实例配置

您希望用于 Group Replication 的服务器实例必须满足以下要求。

基础设施

  • InnoDB 存储引擎。 数据必须存储在InnoDB事务性存储引擎中。事务乐观执行,然后在提交时检查冲突。如果存在冲突,为了在组内保持一致性,一些事务将被回滚。这意味着需要一个事务性存储引擎。此外,InnoDB提供了一些额外功能,使其在与 Group Replication 一起操作时能更好地管理和处理冲突。使用其他存储引擎,包括临时MEMORY存储引擎,可能会导致 Group Replication 中的错误。在将实例与 Group Replication 一起使用之前,请将任何其他存储引擎中的表转换为使用InnoDB。您可以通过在组成员上设置disabled_storage_engines系统变量来阻止使用其他存储引擎,例如:

    disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
    
  • 主键。 每个要被组复制的表必须有一个定义好的主键,或者等效的主键,其中等效主键是一个非空唯一键。这些键被要求作为表中每一行的唯一标识符,使系统能够通过确定每个事务修改了哪些行来确定哪些事务发生了冲突。组复制有自己内置的主键或主键等效的检查,不使用sql_require_primary_key系统变量执行的检查。您可以在运行组复制的服务器实例上设置sql_require_primary_key=ON,并且您可以为组复制通道设置CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句的REQUIRE_TABLE_PRIMARY_KEY_CHECK选项为ON。但是,请注意,您可能会发现一些在组复制内置检查下允许的事务,在设置sql_require_primary_key=ONREQUIRE_TABLE_PRIMARY_KEY_CHECK=ON时不被允许。

  • 网络性能。 MySQL 组复制被设计用于部署在服务器实例非常接近的集群环境中。组的性能和稳定性可能会受到网络延迟和网络带宽的影响。所有组成员之间必须始终保持双向通信。如果某个服务器实例的入站或出站通信被阻止(例如,由防火墙或连接问题),该成员无法在组中运行,并且组成员(包括存在问题的成员)可能无法报告受影响服务器实例的正确成员状态。

    从 MySQL 8.0.14 开始,您可以在远程组复制服务器之间使用 IPv4 或 IPv6 网络基础设施,或两者混合,进行 TCP 通信。组复制也可以在虚拟专用网络(VPN)上运行,没有任何限制。

    同样从 MySQL 8.0.14 开始,当组复制服务器实例位于同一位置并共享本地组通信引擎(XCom)实例时,会尽可能使用专用输入通道进行通信,而不是 TCP 套接字,以降低开销。对于某些需要远程 XCom 实例之间通信的组复制任务,比如加入一个组,仍然使用 TCP 网络,因此网络性能会影响组的性能。

服务器实例配置

必须按照以下所示配置的选项在组成员的服务器实例上进行配置。

  • 唯一服务器标识符。 使用server_id系统变量为服务器配置一个唯一的服务器 ID,这对于复制拓扑中的所有服务器都是必需的。服务器 ID 必须是介于 1 和(2³²)−1 之间的正整数,并且必须与复制拓扑中任何其他服务器使用的任何其他服务器 ID 不同。

  • 二进制日志激活。 设置--log-bin[=log_file_name]。从 MySQL 8.0 开始,默认情况下启用了二进制日志记录,除非您想更改二进制日志文件的名称,否则不需要指定此选项。组复制会复制二进制日志的内容,因此二进制日志需要处于活动状态才能运行。请参阅第 7.4.4 节,“二进制日志”。

  • 复制更新记录。 设置log_replica_updates=ON(从 MySQL 8.0.26 开始)或log_slave_updates=ON(在 MySQL 8.0.26 之前)。从 MySQL 8.0 开始,此设置是默认的,因此您不需要指定它。组成员需要记录从其提供者在加入时接收并通过复制应用程序应用的事务,并记录他们接收并应用于组中的所有事务。这使得组复制能够通过从现有组成员的二进制日志进行状态传输来进行分布式恢复。

  • 二进制日志行格式。 设置binlog_format=row。这是默认设置,因此您不需要指定它。组复制依赖于基于行的复制格式来在组中的服务器之间一致地传播更改,并提取必要的信息以检测在组中不同服务器上同时执行的事务之间的冲突。从 MySQL 8.0.19 开始,REQUIRE_ROW_FORMAT设置会自动添加到组复制的通道中,以强制在应用事务时使用基于行的复制。请参阅第 19.2.1 节,“复制格式”和第 19.3.3 节,“复制权限检查”。

  • 关闭二进制日志校验和(至 MySQL 8.0.20)。 在 MySQL 8.0.20 及之前的版本中,设置binlog_checksum=NONE。在这些版本中,组复制无法使用校验和,并且不支持其存在于二进制日志中。从 MySQL 8.0.21 开始,组复制支持校验和,因此组成员可以使用默认设置binlog_checksum=CRC32,您不需要指定它。

  • 全局事务标识符开启。gtid_mode=ONenforce_gtid_consistency=ON设置为ON。这些设置不是默认值。基于 GTID 的复制对于 Group Replication 是必需的,它使用全局事务标识符来跟踪已在组中的每个服务器实例上提交的事务。参见第 19.1.3 节,“使用全局事务标识符进行复制”。

  • 复制信息存储库。master_info_repository=TABLErelay_log_info_repository=TABLE设置为TABLE。在 MySQL 8.0 中,这些设置是默认的,FILE设置已被弃用。从 MySQL 8.0.23 开始,这些系统变量的使用已被弃用,因此省略这些系统变量,只允许默认设置。复制应用程序需要将复制元数据写入mysql.slave_master_infomysql.slave_relay_log_info系统表,以确保 Group Replication 插件具有一致的可恢复性和事务管理的复制元数据。参见第 19.2.4.2 节,“复制元数据存储库”。

  • 事务写集提取。transaction_write_set_extraction=XXHASH64设置为XXHASH64,以便在收集要记录到二进制日志的行时,服务器也收集写入集。在 MySQL 8.0 中,这是默认设置,从 MySQL 8.0.26 开始,该系统变量的使用已被弃用。写入集基于每行的主键,并且是一个简化且紧凑的视图,用于唯一标识已更改的行。Group Replication 在所有组成员上使用此信息进行冲突检测和认证。

  • 默认表加密。default_table_encryption设置为所有组成员上的相同值。默认模式和表空间加密可以启用(ON)或禁用(OFF,默认值),只要所有成员的设置相同即可。

  • 表名小写。lower_case_table_names设置为所有组成员上的相同值。对于使用InnoDB存储引擎的情况,设置为 1 是正确的,这是 Group Replication 所需的。请注意,这个设置在所有平台上都不是默认值。

  • 二进制日志依赖跟踪。binlog_transaction_dependency_tracking设置为WRITESET可以根据组的工作负载提高组成员的性能。虽然在应用中继日志中的事务时,组复制在认证后进行自己的并行化,独立于为binlog_transaction_dependency_tracking设置的任何值,但是这个值确实影响了事务在组复制成员的二进制日志中的写入方式。这些日志中的依赖信息用于协助从捐赠者的二进制日志进行分布式恢复的状态传输过程,每当成员加入或重新加入组时都会发生。

    注意

    replica_preserve_commit_order设置为ON时,将binlog_transaction_dependency_tracking设置为WRITESET与将其设置为WRITESET_SESSION具有相同的效果。

  • 多线程应用程序。 组复制成员可以配置为多线程副本,使事务可以并行应用。从 MySQL 8.0.27 开始,默认情况下所有副本都配置为多线程。系统变量replica_parallel_workers(从 MySQL 8.0.26 开始)或slave_parallel_workers(MySQL 8.0.26 之前)的非零值启用了成员上的多线程应用程序。从 MySQL 8.0.27 开始,默认值为 4 个并行应用程序线程,最多可以指定 1024 个并行应用程序线程。对于多线程副本,还需要以下设置,这些设置是从 MySQL 8.0.27 开始的默认设置:

    replica_preserve_commit_order=ON(从 MySQL 8.0.26 开始)或slave_preserve_commit_order=ON(MySQL 8.0.26 之前)

    此设置是为了确保并行事务的最终提交与原始事务的顺序相同。组复制依赖于围绕所有参与成员以相同顺序接收和应用已提交事务的一致性机制构建。

    replica_parallel_type=LOGICAL_CLOCK(从 MySQL 8.0.26 开始)或slave_parallel_type=LOGICAL_CLOCK(MySQL 8.0.26 之前)

    此设置需要与replica_preserve_commit_order=ONslave_preserve_commit_order=ON一起使用。它指定了用于决定在副本上允许哪些事务并行执行的策略。

    设置replica_parallel_workers=0slave_parallel_workers=0会禁用并行执行,使得复制品只有一个应用程序线程和没有协调器线程。在这种设置下,replica_parallel_typeslave_parallel_type以及replica_preserve_commit_orderslave_preserve_commit_order选项不起作用,会被忽略。从 MySQL 8.0.27 开始,如果在复制品上使用 GTIDs 时禁用了并行执行,复制品实际上会使用一个并行工作者,以利用在不访问文件位置的情况下重试事务的方法。然而,这种行为对用户不会有任何改变。

  • 分离的 XA 事务。 MySQL 8.0.29 及更高版本支持分离的 XA 事务。分离的事务是指一旦准备好,就不再与当前会话连接的事务。这会自动发生作为执行XA PREPARE的一部分。准备好的 XA 事务可以由另一个连接提交或回滚,然后当前会话可以启动另一个 XA 事务或本地事务,而无需等待刚刚准备的事务完成。

    当启用分离的 XA 事务支持(xa_detach_on_prepare = ON)时,任何连接到此服务器的连接都可以列出(使用XA RECOVER)、回滚或提交任何准备好的 XA 事务。此外,在分离的 XA 事务中不能使用临时表。

    通过将xa_detach_on_prepare设置为OFF可以禁用对分离的 XA 事务的支持,但这并不推荐。特别是,如果此服务器正在设置为 MySQL 组复制中的一个实例,您应该将此变量保持为其默认值(ON)。

    更多信息请参见 Section 15.3.8.2, “XA Transaction States”。

20.3.2 Group Replication 限制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-limitations.html

  • 组大小限制

  • 事务大小限制

Group Replication 存在以下已知限制。请注意,在故障转移事件期间,多主模式组的限制和问题也可能适用于单主模式集群,而新选举的主节点会清空其来自旧主节点的应用程序队列。

提示

Group Replication 是基于 GTID 的复制构建的,因此您还应该注意 Section 19.1.3.7, “使用 GTID 进行复制的限制”。

  • --upgrade=MINIMAL选项。 Group Replication 无法在使用 MINIMAL 选项(--upgrade=MINIMAL)进行 MySQL Server 升级后启动,因为该选项不会升级复制内部所依赖的系统表。

  • 间隙锁。 Group Replication 的并发事务认证过程不考虑间隙锁,因为间隙锁的信息在InnoDB之外不可用。有关更多信息,请参阅间隙锁。

    注意

    对于多主模式下的组,除非您的应用程序依赖于REPEATABLE READ语义,我们建议在 Group Replication 中使用READ COMMITTED隔离级别。 InnoDB 在READ COMMITTED中不使用间隙锁,这使得 InnoDB 内部的本地冲突检测与 Group Replication 执行的分布式冲突检测保持一致。对于单主模式下的组,只有主节点接受写操作,因此READ COMMITTED隔离级别对于 Group Replication 并不重要。

  • 表锁和命名锁。 认证过程不考虑表锁(参见 Section 15.3.6, “LOCK TABLES 和 UNLOCK TABLES 语句”)或命名锁(参见GET_LOCK())。

  • 二进制日志校验和。 截至 MySQL 8.0.20,Group Replication 无法使用校验和,也不支持二进制日志中的校验和,因此在配置服务器实例成为组成员时,必须设置binlog_checksum=NONE。从 MySQL 8.0.21 开始,Group Replication 支持校验和,因此组成员可以使用默认设置binlog_checksum=CRC32binlog_checksum 的设置不必对组中的所有成员相同。

    当校验和可用时,Group Replication 不会使用它们来验证group_replication_applier通道上的传入事件,因为事件是从多个来源写入到中继日志中的,而在它们实际写入到原始服务器的二进制日志之前,校验和是不会生成的。校验和用于验证group_replication_recovery通道上的事件的完整性,以及组成员上的任何其他复制通道上的事件。

  • 可串行化隔离级别。 SERIALIZABLE 隔离级别在多主组中默认不受支持。将事务隔离级别设置为SERIALIZABLE会配置 Group Replication 拒绝提交事务。

  • 并发 DDL 与 DML 操作。 在使用多主模式时,不支持针对同一对象执行并发数据定义语句和数据操作语句,但在不同的服务器上执行。在对象上执行数据定义语言(DDL)语句期间,在不同服务器实例上执行相同对象的并发数据操作语言(DML)存在冲突的风险,因为在不同实例上执行的冲突 DDL 可能不会被检测到。

  • 具有级联约束的外键。 多主模式组(所有成员都配置为group_replication_single_primary_mode=OFF)不支持具有多级外键依赖关系的表,特别是定义了CASCADING外键约束的表。这是因为由多主模式组执行的导致级联操作的外键约束可能导致未检测到的冲突,并导致组成员之间的数据不一致。因此,我们建议在用于多主模式组的服务器实例上设置group_replication_enforce_update_everywhere_checks=ON以避免未检测到的冲突。

    在单主模式下,这不是问题,因为它不允许并发写入到组的多个成员,因此不存在未检测到的冲突风险。

  • 多主模式死锁。 当一个组以多主模式运行时,SELECT .. FOR UPDATE语句可能导致死锁。这是因为锁不在组的成员之间共享,因此对于这样的语句的期望可能无法实现。

  • 复制过滤器。 不能在配置为 Group Replication 的 MySQL 服务器实例上使用全局复制过滤器,因为在某些服务器上过滤事务会导致组无法达成一致状态。可以在与 Group Replication 无直接关系的复制通道上使用特定通道的复制过滤器,例如,当一个组成员同时充当组外源的副本时。不能在group_replication_appliergroup_replication_recovery通道上使用。

  • 加密连接。 MySQL Server 自 MySQL 8.0.16 起支持 TLSv1.3 协议,前提是 MySQL 使用了 OpenSSL 1.1.1 或更高版本进行编译。在 MySQL 8.0.16 和 MySQL 8.0.17 中,如果服务器支持 TLSv1.3,则该协议在组通信引擎中不受支持,无法被 Group Replication 使用。从 MySQL 8.0.18 开始,Group Replication 支持 TLSv1.3,可以用于组通信连接和分布式恢复连接。

    在 MySQL 8.0.18 中,TLSv1.3 可以用于 Group Replication 的分布式恢复连接,但group_replication_recovery_tls_versiongroup_replication_recovery_tls_ciphersuites系统变量不可用。因此,捐赠服务器必须允许使用至少一个默认启用的 TLSv1.3 密码套件,如第 8.3.2 节“加密连接 TLS 协议和密码套件”中列出的那样。从 MySQL 8.0.19 开始,您可以使用选项配置客户端支持任意选择的密码套件,包括仅使用非默认密码套件。

  • 克隆操作。 Group Replication 启动并管理用于分布式恢复的克隆操作,但已设置为支持克隆的组成员也可以参与用户手动启动的克隆操作。在 MySQL 8.0.20 之前的版本中,如果操作涉及正在运行 Group Replication 的组成员,则无法手动启动克隆操作。从 MySQL 8.0.20 开始,只要克隆操作不会删除并替换接收方的数据,就可以执行此操作。因此,如果 Group Replication 正在运行,则启动克隆操作的语句必须包含DATA DIRECTORY子句。请参阅 Section 20.5.4.2.4, “Cloning for Other Purposes”。

组大小限制

单个复制组中可以成为成员的 MySQL 服务器的最大数量为 9。如果更多成员尝试加入组,则其请求将被拒绝。这个限制是通过测试和基准测试确定的,作为组在稳定的局域网上可靠运行的安全边界。

事务大小限制

如果单个事务导致消息内容过大,以至于在 5 秒窗口内无法在组成员之间复制消息,那么成员可能会被怀疑失败,然后被驱逐,仅仅因为它们正忙于处理事务。大型事务也可能导致系统由于内存分配问题而变慢。为避免这些问题,请使用以下缓解措施:

  • 如果由于大型消息而发生不必要的驱逐,请使用系统变量group_replication_member_expel_timeout在怀疑失败的成员被驱逐之前提供额外的时间。在初始的 5 秒检测期之后,您可以允许多达一小时的时间,然后才将怀疑的成员从组中驱逐。从 MySQL 8.0.21 开始,默认情况下额外允许 5 秒。

  • 在可能的情况下,在交由 Group Replication 处理之前,尽量限制事务的大小。例如,将与LOAD DATA一起使用的文件拆分为较小的块。

  • 使用系统变量group_replication_transaction_size_limit来指定组接受的最大事务大小。在 MySQL 8.0 中,此系统变量默认为最大事务大小为 150000000 字节(约 143 MB)。超过此大小的事务将被回滚,并且不会发送到 Group Replication 的 Group Communication System (GCS)以分发给组。根据您需要组容忍的最大消息大小调整此变量的值,要牢记处理事务所需的时间与其大小成正比。

  • 使用系统变量group_replication_compression_threshold来指定应用压缩的消息大小阈值。该系统变量默认为 1000000 字节(1 MB),因此大消息会自动进行压缩。当 Group Replication 的 Group Communication System(GCS)接收到一个由group_replication_transaction_size_limit设置允许但超过group_replication_compression_threshold设置的消息时,将执行压缩。更多信息,请参见第 20.7.4 节,“消息压缩”。

  • 使用系统变量group_replication_communication_max_message_size来指定应用分段的消息大小阈值。该系统变量默认为 10485760 字节(10 MiB),因此大消息会自动进行分段。如果压缩后的消息仍超过group_replication_communication_max_message_size限制,GCS 将在压缩后执行分段。为了使复制组使用分段,所有组成员必须使用 MySQL 8.0.16 或更高版本,并且组使用的 Group Replication 通信协议版本必须允许分段。更多信息,请参见第 20.7.5 节,“消息分段”。

最大交易大小、消息压缩和消息分段都可以通过指定相关系统变量的零值来停用。如果您已停用了所有这些保护措施,那么在复制组成员的应用程序线程可以处理的消息的上限大小是成员的replica_max_allowed_packetslave_max_allowed_packet系统变量的值,这些变量的默认和最大值为 1073741824 字节(1 GB)。当接收成员尝试处理超过此限制的消息时,消息将失败。组成员可以发起并尝试传输到组的消息的上限大小为 4294967295 字节(约 4 GB)。这是接受由组复制(XCom,一种 Paxos 变体)的组通信引擎处理后的消息的数据包大小的硬限制,GCS 在处理消息后接收它们。当发起成员尝试广播超过此限制的消息时,消息将失败。

20.4 监视组复制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-monitoring.html

20.4.1 GTIDs 和组复制

20.4.2 组复制服务器状态

20.4.3 复制组成员表

20.4.4 复制组成员统计表

您可以使用 MySQL 性能模式 监视组复制。这些性能模式表显示特定于组复制的信息:

  • replication_group_member_stats:参见 第 20.4.4 节,“复制组成员统计表”。

  • replication_group_members:参见 第 20.4.3 节,“复制组成员表”。

  • replication_group_communication_information:参见 第 29.12.11.15 节,“复制组通信信息表”。

这些性能模式复制表还显示与组复制相关的信息:

  • replication_connection_status 显示有关组复制的信息,例如从组接收的事务以及在应用程序队列(中继日志)中排队的事务。

  • replication_applier_status 显示与组复制相关的通道和线程的状态。这些也可以用于监视各个工作线程正在做什么。

组复制插件创建的复制通道在此处列出:

  • group_replication_recovery: 用于与分布式恢复相关的复制更改。

  • group_replication_applier: 用于来自组的传入更改,以应用直接来自组的事务。

有关影响组复制的系统变量的信息,请参见第 20.9.1 节,“组复制系统变量”。有关提供有关组复制信息的状态变量的信息,请参见第 20.9.2 节,“组复制状态变量”。

从 MySQL 8.0.21 开始,与组复制生命周期事件相关的消息(除错误外)被分类为系统消息;这些消息始终写入复制组成员的错误日志。您可以使用此信息来查看给定服务器在复制组中的成员资格历史。(以前,这些事件被分类为信息消息;对于 MySQL 服务器的版本早于 8.0.21 的情况,可以通过将log_error_verbosity设置为3将其添加到错误日志中。)

影响整个组的一些生命周期事件会在每个组成员上记录,例如新成员进入ONLINE状态或进行主要选举。其他事件仅在事件发生的成员上记录,例如在成员上启用或禁用超级只读模式,或成员离开组。如果发生频繁,一些可能指示问题的生命周期事件将记录为警告消息,包括成员变得无法访问然后再次可访问,以及成员通过从二进制日志进行状态传输或通过远程克隆操作开始分布式恢复。

注意

如果您正在使用mysqladmin监视一个或多个辅助实例,您应该知道,此实用程序执行的FLUSH STATUS语句会在本地实例上创建一个 GTID 事件,这可能会影响未来的组操作。

20.4.1 GTIDs 和组复制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-gtids.html

组复制使用 GTIDs(全局事务标识符)来精确跟踪每个服务器实例上已提交的事务。所有组成员都需要设置gtid_mode=ONenforce_gtid_consistency=ON。从客户端接收的事务由接收它们的组成员分配一个 GTID。从组外部源服务器通过异步复制通道接收到的任何复制事务在到达组成员时保留它们的 GTID。

从客户端接收的事务分配的 GTID 使用group_replication_group_name系统变量指定的组名作为标识符的 UUID 部分,而不是接收事务的单个组成员的服务器 UUID。因此,所有直接由组接收的事务都可以被识别并分组在 GTID 集合中,不管最初接收它们的成员是谁。每个组成员都有一块连续的 GTID 保留供其使用,当这些 GTID 被消耗完时,它会保留更多。group_replication_gtid_assignment_block_size系统变量设置了块的大小,默认情况下每个块中有 100 万个 GTID。

当新成员加入时,由组自动生成的视图更改事件(View_change_log_event)在二进制日志中记录时被赋予 GTID。默认情况下,这些事件的 GTID 也使用group_replication_group_name系统变量指定的组名作为标识符的 UUID 部分。从 MySQL 8.0.26 开始,您可以设置 Group Replication 系统变量group_replication_view_change_uuid以在视图更改事件的 GTID 中使用替代 UUID,以便它们易于与从客户端接收的事务区分开来。如果您的设置允许在组之间进行故障切换,并且您需要识别和丢弃特定于备份组的事务,则这可能很有用。替代 UUID 必须与成员的服务器 UUID 不同。它还必须与使用CHANGE REPLICATION SOURCE TO语句的ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS选项应用于匿名事务的 GTID 中的任何 UUID 不同。

从 MySQL 8.0.27 开始,设置 GTID_ONLY=1REQUIRE_ROW_FORMAT = 1SOURCE_AUTO_POSITION = 1 适用于 Group Replication 通道 group_replication_appliergroup_replication_recovery。这些设置在创建 Group Replication 通道时自动设置,或者当复制组中的成员服务器升级到 8.0.27 或更高版本时自动设置。通常使用 CHANGE REPLICATION SOURCE TO 语句设置这些选项,但请注意,您无法为 Group Replication 通道禁用它们。设置了这些选项后,组成员不会在这些通道的复制元数据存储库中持久保存文件名和文件位置。在必要时,GTID 自动定位和 GTID 自动跳过用于定位正确的接收器和应用程序位置。

额外事务

如果加入成员的 GTID 集中存在在组中现有成员中不存在的事务,则不允许完成分布式恢复过程,并且无法加入该组。如果进行了远程克隆操作,则这些事务将被删除和丢失,因为加入成员的数据目录被擦除。如果从捐赠者的二进制日志进行状态传输,则这些事务可能与组的事务发生冲突。

如果在 Group Replication 停止时在实例上执行管理事务,则可能会存在额外的事务。为了避免以这种方式引入新事务,请在发出管理语句之前始终将 sql_log_bin 系统变量的值设置为 OFF,然后在之后设置回 ON

SET SQL_LOG_BIN=0;
<administrator action>
SET SQL_LOG_BIN=1;

将此系统变量设置为 OFF 意味着从那一点开始发生的事务不会写入二进制日志,并且不会分配 GTID。

如果加入成员存在额外的事务,请检查受影响服务器的二进制日志,查看额外事务的实际内容。将加入成员的数据和 GTID 集与当前组中的成员进行协调的最安全方法是使用 MySQL 的克隆功能,将内容从组中的一个服务器传输到受影响的服务器。有关如何执行此操作的说明,请参见 Section 7.6.7.3, “克隆远程数据”。如果需要该事务,请在成员成功重新加入后重新运行它。

20.4.2 Group Replication Server States

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-server-states.html

Group Replication 群组成员的状态显示其在群组中的当前角色。Performance Schema 表replication_group_members显示了群组中每个成员的状态。如果群组完全正常运行且所有成员正常通信,则所有成员对所有其他成员报告相同的状态。但是,已离开群组或处于网络分区的成员无法准确报告其他服务器的信息。在这种情况下,该成员不会尝试猜测其他服务器的状态,而是将它们报告为不可访问。

一个群组成员可以处于以下状态:

ONLINE

服务器是群组的活跃成员,并处于完全运行状态。其他群组成员可以连接到它,客户端(如果适用)也可以连接到它。只有当成员处于ONLINE状态时,它才会与群组完全同步,并参与其中。

RECOVERING

服务器已加入一个群组,并正在成为活跃成员的过程中。当前正在进行分布式恢复,成员正在接收来自捐赠者的状态传输,使用远程克隆操作或捐赠者的二进制日志。此状态为

更多信息,请参见 Section 20.5.4, “Distributed Recovery”。

OFFLINE

Group Replication 插件已加载,但成员不属于任何群组。在成员加入或重新加入群组时,可能会暂时出现此状态。

ERROR

该成员处于错误状态,并且作为群组成员无法正常运行。成员可能在应用事务期间或恢复阶段进入错误状态。处于此状态的成员不参与群组的事务。有关错误状态可能原因的更多信息,请参见 Section 20.7.7, “Responses to Failure Detection and Network Partitioning”。

根据group_replication_exit_state_action设置的退出操作,成员处于只读模式(super_read_only=ON),也可能处于离线模式(offline_mode=ON)。请注意,遵循OFFLINE_MODE退出操作的离线模式服务器显示为ERROR状态,而不是OFFLINE。采用ABORT_SERVER退出操作的服务器将关闭并从组的视图中移除。更多信息,请参见 Section 20.7.7.4, “退出操作”。

当成员加入或重新加入复制组时,在组完成兼容性检查并接受其为成员之前,其状态可能显示为ERROR

UNREACHABLE

本地故障检测器怀疑无法联系到成员,因为组的消息超时。这可能发生在成员非自愿断开连接的情况下。如果您在其他服务器看到此状态,也可能意味着您查询此表的成员是分区的一部分,组的一部分服务器可以相互联系,但无法联系组中的其他服务器。更多信息,请参见 Section 20.7.8, “处理网络分区和失去法定人数”。

请参见 Section 20.4.3, “复制组成员表”,了解性能模式表内容的示例。

20.4.3 The replication_group_members Table

dev.mysql.com/doc/refman/8.0/en/group-replication-replication-group-members.html

performance_schema.replication_group_members表用于监视组成员的不同服务器实例的状态。表中的信息在视图更改时更新,例如当新成员加入时动态更改组配置时。在那时,服务器交换一些元数据以同步自己并继续共同合作。信息在所有作为复制组成员的服务器实例之间共享,因此可以从任何成员查询所有组成员的信息。该表可用于获取复制组状态的高级视图,例如通过发出:

SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | d391e9ee-2691-11ec-bf61-00059a3c7a00 | example1    |        4410 | ONLINE       | PRIMARY     | 8.0.27         | XCom                       |
| group_replication_applier | e059ce5c-2691-11ec-8632-00059a3c7a00 | example2    |        4420 | ONLINE       | SECONDARY   | 8.0.27         | XCom                       |
| group_replication_applier | ecd9ad06-2691-11ec-91c7-00059a3c7a00 | example3    |        4430 | ONLINE       | SECONDARY   | 8.0.27         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.0007 sec)

根据这个结果,我们可以看到该组由三个成员组成。表中显示了每个成员的server_uuid,以及成员的主机名和端口号,客户端用于连接的信息。MEMBER_STATE列显示了第 20.4.2 节,“组复制服务器状态”中的一个状态,在这种情况下显示该组的所有三个成员都是ONLINEMEMBER_ROLE列显示有两个从属节点和一个主节点。因此,该组必须在单主模式下运行。MEMBER_VERSION列在升级组并合并运行不同 MySQL 版本的成员时可能会有用。MEMBER_COMMUNICATION_STACK列显示了组使用的通信堆栈。

关于MEMBER_HOST值及其对分布式恢复过程的影响的更多信息,请参见第 20.2.1.3 节,“用于分布式恢复的用户凭据”。

20.4.4 The replication_group_member_stats Table

译文:dev.mysql.com/doc/refman/8.0/en/group-replication-replication-group-member-stats.html

每个复制组中的成员都会对组接收的事务进行认证和应用。关于认证者和应用者过程的统计信息对于了解应用程序队列的增长情况、发现了多少冲突、检查了多少事务、哪些事务在所有地方都已提交等方面非常有用。

performance_schema.replication_group_member_stats 表提供了与认证过程相关的组级信息,以及每个复制组成员接收和发起的事务的统计信息。这些信息在所有作为复制组成员的服务器实例之间共享,因此可以从任何成员查询所有组成员的信息。请注意,远程成员的统计信息刷新由group_replication_flow_control_period 选项中指定的消息周期控制,因此这些统计信息可能与在进行查询的成员本地收集的统计信息略有不同。要使用此表监视 Group Replication 成员,请执行以下语句:

mysql> SELECT * FROM performance_schema.replication_group_member_stats\G

从 MySQL 8.0.19 开始,您还可以使用以下语句:

mysql> TABLE performance_schema.replication_group_member_stats\G

这些列对于监视组中连接的成员的性能非常重要。假设组中的一个成员总是报告其队列中的事务数量比其他成员多。这意味着该成员延迟了,并且无法跟上组中其他成员的步伐。根据这些信息,您可以决定是将该成员从组中移除,还是延迟其他组成员的事务处理,以减少排队事务的数量。这些信息还可以帮助您决定如何调整 Group Replication 插件的流量控制,请参阅 Section 20.7.2, “Flow Control”。

20.5 群组复制操作

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-operations.html

20.5.1 配置在线群组

20.5.2 重新启动一个群组

20.5.3 事务一致性保证

20.5.4 分布式恢复

20.5.5 支持 IPv6 和混合 IPv6 和 IPv4 群组

20.5.6 使用 MySQL 企业备份与群组复制

本节解释了管理群组的常见操作。

20.5.1 配置在线组

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-online-group.html

20.5.1.1 更改主服务器

20.5.1.2 改变组模式

20.5.1.3 使用 Group Replication 组写一致性

20.5.1.4 设置组的通信协议版本

20.5.1.5 配置成员操作

您可以在 Group Replication 运行时使用一组函数配置在线组,这些函数依赖于组操作协调员。这些函数由 Group Replication 插件在 8.0.13 及更高版本中安装。本节描述了如何对运行中的组进行更改以及可用的功能。

重要提示

协调员要能够在运行中的组上配置组范围的操作,所有成员必须运行 MySQL 8.0.13 或更高版本,并安装了这些功能。

要使用这些功能,请连接到运行中的组的成员,并使用SELECT语句调用该函数。 Group Replication 插件处理操作及其参数,协调员将其发送给所有对调用函数的成员可见的成员。如果操作被接受,所有成员执行该操作并在完成后发送终止消息。一旦所有成员声明操作已完成,调用成员将结果返回给客户端。

在配置整个组时,操作的分布性意味着它们与 Group Replication 插件的许多进程进行交互,因此您应该遵守以下规定:

您可以在任何地方发出配置操作。 如果要将成员 A 设置为新的主服务器,则无需在成员 A 上调用操作。所有操作都以协调的方式发送并在所有组成员上执行。此外,操作的分布式执行具有不同的影响:如果发出操作的成员死亡,则任何已经运行的配置过程将继续在其他成员上运行。在发出操作的成员死亡的极少情况下,您仍然可以使用监控功能确保其他成员成功完成操作。

所有成员必须在线。 为了简化迁移或选举过程并确保它们尽可能快速,组不得包含当前处于分布式恢复过程中的任何成员,否则配置操作将被发出语句的成员拒绝。

在配置更改期间,没有成员可以加入组。 任何尝试在协调的配置更改期间加入组的成员都会离开组并取消其加入过程。

一次只能进行一个配置更改。 正在执行配置更改的组不能接受任何其他组的配置更改,因为并发的配置操作可能导致成员分歧。

所有成员必须运行 MySQL 8.0.13 或更高版本。 由于配置操作的分布式特性,所有成员必须识别它们才能执行它们。如果任何运行 MySQL Server 版本低于 8.0.12 的服务器存在于组中,则操作将被拒绝。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-change-primary.html

20.5.1.1 更改主节点

本节解释了如何更改单一主节点组中的主节点,使用group_replication_set_as_primary()函数,该函数可以在组的任何成员上运行。执行此操作后,当前主节点将成为只读辅助节点,指定的组成员将成为读写主节点;这取代了第 20.1.3.1 节,“单一主节点模式”中描述的通常的主节点选举过程。

如果标准的源到副本复制通道正在现有的主节点上运行,除了组复制通道之外,您必须在更改主节点之前停止该复制通道。您可以使用性能模式表replication_group_members中的MEMBER_ROLE列,或者group_replication_primary_member状态变量来识别当前的主节点。

如果所有成员未运行相同的 MySQL 服务器版本,则只能指定运行组中最低 MySQL 服务器版本的新主节点。此保护措施旨在确保组与新功能保持兼容。这适用于所有 MySQL 版本,并从 MySQL 8.0.17 开始强制执行。

组正在等待的任何未提交事务必须在操作完成之前提交、回滚或终止。在 MySQL 8.0.29 之前,该函数会等待现有主节点上的所有活动事务结束,包括在使用该函数后启动的传入事务。从 MySQL 8.0.29 开始,您可以为在使用该函数时正在运行的事务指定从 0 秒(立即)到 3600 秒(60 分钟)的超时时间。为使超时生效,组的所有成员必须运行 MySQL 8.0.29 或更高版本。超时没有默认设置,因此如果您不设置它,等待时间没有上限,新事务可以在此期间启动。

当超时到期时,对于尚未达到提交阶段的任何事务,客户端会被断开连接,以防事务继续进行。已达到提交阶段的事务将被允许完成。设置超时还会阻止从那时起在主服务器上启动新事务。即使它们不修改任何数据,显式定义的事务(使用START TRANSACTIONBEGIN语句)也会受到超时、断开连接和传入事务阻止的影响。为了允许在函数运行时检查主服务器,允许执行不修改数据的单个语句,如一致性规则下允许的查询中列出的语句。

通过发出以下语句,传递成员的server_uuid,该成员将成为组的新主要成员:

SELECT group_replication_set_as_primary(*member_uuid*);

在 MySQL 8.0.29 及更高版本中,您可以添加一个超时,如下所示:

SELECT group_replication_set_as_primary(‘00371d66-3c45-11ea-804b-080027337932’, 300)

要检查超时的状态,请使用性能模式threads表中的PROCESSLIST_INFO列,如下所示:

mysql> SELECT NAME, PROCESSLIST_INFO FROM performance_schema.threads 
 -> WHERE NAME="thread/group_rpl/THD_transaction_monitor"\G
*************************** 1\. row ***************************
            NAME: thread/group_rpl/THD_transaction_monitor
PROCESSLIST_INFO: Group replication transaction monitor: Stopped client connections

状态显示了事务监控线程何时被创建,新事务何时被停止,带有未提交事务的客户端连接何时被断开,最后,进程何时完成并允许新事务再次进行。

在操作运行时,您可以通过发出以下语句来检查其进度:

mysql> SELECT event_name, work_completed, work_estimated 
 -> FROM performance_schema.events_stages_current 
 -> WHERE event_name LIKE "%stage/group_rpl%"\G
*************************** 1\. row ***************************
    EVENT_NAME: stage/group_rpl/Primary Election: Waiting for members to turn on super_read_only
WORK_COMPLETED: 3
WORK_ESTIMATED: 5

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-changing-group-mode.html

20.5.1.2 更改组模式

本节解释了如何更改组运行的模式,即单主或多主。用于更改组模式的函数可以在任何成员上运行。

切换到单主模式

使用group_replication_switch_to_single_primary_mode()函数通过执行以下命令将运行在多主模式下的组切换到单主模式:

SELECT group_replication_switch_to_single_primary_mode()

当您切换到单主模式时,所有组成员上也会禁用严格的一致性检查,这是单主模式所要求的(group_replication_enforce_update_everywhere_checks=OFF)。

如果没有传入字符串,在结果为单主组的新主要选举中,遵循 20.1.3.1 节,“单主模式”中描述的选举策略。要覆盖选举过程并在过程中配置多主组的特定成员作为新主要成员,请获取成员的server_uuid并将其传递给group_replication_switch_to_single_primary_mode()。例如,执行以下命令:

SELECT group_replication_switch_to_single_primary_mode(*member_uuid*);

如果在运行 MySQL Server 版本为 8.0.17 的成员上调用该函数,并且所有成员都运行 MySQL Server 版本为 8.0.17 或更高版本,则只能指定运行最低 MySQL Server 版本的新主要成员,基于补丁版本。这个保障是为了确保组保持与新功能的兼容性。如果不指定新的主要成员,选举过程将考虑组成员的补丁版本。

如果任何成员运行的 MySQL Server 版本介于 MySQL 8.0.13 和 MySQL 8.0.16 之间,则不会强制执行此保障,并且您可以指定任何新的主要成员,但建议选择运行组中最低 MySQL Server 版本的主要成员。如果不指定新的主要成员,选举过程仅考虑组成员的主要版本。

在操作运行时,您可以通过执行以下命令来检查其进度:

SELECT event_name, work_completed, work_estimated FROM performance_schema.events_stages_current WHERE event_name LIKE "%stage/group_rpl%";
+----------------------------------------------------------------------------+----------------+----------------+
| event_name                                                                 | work_completed | work_estimated |
+----------------------------------------------------------------------------+----------------+----------------+
| stage/group_rpl/Primary Switch: waiting for pending transactions to finish |              4 |             20 |
+----------------------------------------------------------------------------+----------------+----------------+
切换到多主模式

使用group_replication_switch_to_multi_primary_mode()函数通过执行以下命令将运行在单主模式下的组切换到多主模式:

SELECT group_replication_switch_to_multi_primary_mode()

在执行一些协调的组操作以确保数据的安全性和一致性之后,所有属于该组的成员都变为主节点。

当您将在单主模式下运行的组更改为多主模式时,运行 MySQL 8.0.17 或更高版本的成员如果运行的 MySQL 服务器版本高于组中存在的最低版本,则会自动处于只读模式。运行 MySQL 8.0.16 或更低版本的成员不执行此检查,并始终处于读写模式。

当操作运行时,您可以通过发出以下命令来检查其进度:

SELECT event_name, work_completed, work_estimated FROM performance_schema.events_stages_current WHERE event_name LIKE "%stage/group_rpl%";
+----------------------------------------------------------------------+----------------+----------------+
| event_name                                                           | work_completed | work_estimated |
+----------------------------------------------------------------------+----------------+----------------+
| stage/group_rpl/Multi-primary Switch: applying buffered transactions |              0 |              1 |
+----------------------------------------------------------------------+----------------+----------------+

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-group-write-consensus.html

20.5.1.3 使用 Group Replication 群组写共识

本节介绍如何检查和配置群组在任何时候的最大共识实例数。这个最大值被称为群组的事件视界,是群组可以并行执行的最大共识实例数。这使您能够微调您的 Group Replication 部署的性能。例如,默认值为 10 适用于在局域网上运行的群组,但对于在较慢的网络(如广域网)上运行的群组,增加此数字以提高性能。

检查群组的写并发性

使用group_replication_get_write_concurrency()函数,在运行时检查群组的事件视界值,通过发出:

SELECT group_replication_get_write_concurrency();
配置群组的写并发性

使用group_replication_set_write_concurrency()函数,设置系统可以并行执行的最大共识实例数,通过发出:

SELECT group_replication_set_write_concurrency(*instances*);

其中instances是新的最大共识实例数。需要GROUP_REPLICATION_ADMIN权限才能使用此功能。

dev.mysql.com/doc/refman/8.0/en/group-replication-communication-protocol.html

20.5.1.4 设置组的通信协议版本

从 MySQL 8.0.16 开始,Group Replication 具有组的通信协议的概念。Group Replication 通信协议版本可以被明确管理,并设置为适应您希望组支持的最旧 MySQL Server 版本。这使得可以从不同 MySQL Server 版本的成员组成组,同时确保向后兼容性。

  • MySQL 5.7.14 版本允许消息的压缩(参见 Section 20.7.4, “Message Compression”)。

  • MySQL 8.0.16 版本还允许消息的分段(参见 Section 20.7.5, “Message Fragmentation”)。

  • MySQL 8.0.27 版本还允许在单主模式下,当group_replication_paxos_single_leader设置为 true 时,组通信引擎可以与单一一致性领导者一起运行(参见 Section 20.7.3, “Single Consensus Leader”)。

所有组成员必须使用相同的通信协议版本,以便组成员可以处于不同的 MySQL Server 版本,但只发送所有组成员都能理解的消息。

MySQL 服务器在版本 X 下,只有当复制组的通信协议版本小于或等于 X 时,才能加入并达到ONLINE状态。当新成员加入复制组时,它会检查现有成员所宣布的通信协议版本。如果加入成员支持该版本,则加入该组并使用组宣布的通信协议,即使该成员支持额外的通信能力。如果加入成员不支持通信协议版本,则会被从组中驱逐。

如果两个成员尝试在同一成员变更事件中加入,只有当两个成员的通信协议版本已经与组的通信协议版本兼容时,它们才能加入。与组不同通信协议版本的成员必须独立加入。例如:

  • 一个 MySQL Server 8.0.16 实例可以成功加入使用通信协议版本 5.7.24 的组。

  • 一个 MySQL Server 5.7.24 实例无法成功加入使用通信协议版本 8.0.16 的组。

  • 两个 MySQL Server 8.0.16 实例不能同时加入使用通信协议版本 5.7.24 的组。

  • 两个 MySQL Server 8.0.16 实例可以同时加入使用通信协议版本 8.0.16 的组。

您可以使用group_replication_get_communication_protocol()函数检查组正在使用的通信协议,该函数返回组支持的最旧 MySQL Server 版本。组的所有现有成员返回相同的通信协议版本。例如:

SELECT group_replication_get_communication_protocol();
+------------------------------------------------+
| group_replication_get_communication_protocol() |
+------------------------------------------------+
| 8.0.16                                         |
+------------------------------------------------+

请注意,group_replication_get_communication_protocol()函数返回组支持的最低 MySQL 版本,这可能与传递给group_replication_set_communication_protocol()函数的版本号不同,并且可能与您在使用该函数的成员上安装的 MySQL Server 版本不同。

如果您需要更改组的通信协议版本,以便早期版本的成员可以加入,请使用group_replication_set_communication_protocol()函数指定您希望允许的最旧成员的 MySQL Server 版本。如果可能的话,这将使组回退到兼容的通信协议版本。使用此函数需要GROUP_REPLICATION_ADMIN权限,并且在发出语句时,所有现有组成员必须在线,没有多数成员丢失。例如:

SELECT group_replication_set_communication_protocol("5.7.25");

如果您将复制组的所有成员升级到新的 MySQL Server 版本,则组的通信协议版本不会自动升级以匹配。如果您不再需要支持早期版本的成员,您可以使用group_replication_set_communication_protocol()函数将通信协议版本设置为您已经升级成员的新 MySQL Server 版本。例如:

SELECT group_replication_set_communication_protocol("8.0.16");

group_replication_set_communication_protocol() 函数被实现为一个组操作,因此在组的所有成员上同时执行。组操作开始缓冲消息,并等待任何正在进行中的传出消息的传递完成,然后更改通信协议版本并发送缓冲消息。如果在更改通信协议版本后的任何时间点,有成员尝试加入组,组成员会宣布新的协议版本。

MySQL InnoDB 集群在使用 AdminAPI 操作更改集群拓扑结构时,自动透明地管理其成员的通信协议版本。InnoDB 集群始终使用当前所有实例支持的最新通信协议版本,这些实例当前是集群的一部分或正在加入其中。有关详细信息,请参阅 InnoDB 集群和组复制协议。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-member-actions.html

20.5.1.5 配置成员操作

从 MySQL 8.0.26 开始,Group Replication 具有设置组成员在指定情况下采取的操作的能力。可以使用函数单独启用和禁用成员操作。服务器的成员操作配置在离开组后也可以重置为默认值。

管理员(具有GROUP_REPLICATION_ADMIN权限)可以使用group_replication_enable_member_actiongroup_replication_disable_member_action函数在组的主服务器上配置成员操作。然后,成员操作配置(包括所有成员操作以及它们是否启用或禁用)通过 Group Replication 的组消息传播到其他组成员和加入成员。因此,所有组成员都具有相同的成员操作配置。您还可以在不属于任何组的服务器上配置成员操作,只要安装了 Group Replication 插件。在这种情况下,成员操作配置不会传播到任何其他服务器。

如果在使用函数配置成员操作的服务器是组的一部分,则它必须是单主模式下的当前主服务器,并且必须是大多数的一部分。配置更改在 Group Replication 内部被跟踪,但不会被赋予 GTID,并且不会被写入二进制日志,因此不会传播到任何组外的服务器,如下游复制。每次启用或禁用成员操作时,Group Replication 都会增加其成员操作配置的版本号。

成员操作配置传播给成员的方式如下:

  • 在启动组时,引导组的服务器的成员操作配置成为组的配置。

  • 如果组的最低 MySQL Server 版本支持成员操作,则加入成员在加入时进行状态交换过程中接收组的成员操作配置。在这种情况下,加入成员将自己的成员操作配置替换为组的配置。

  • 如果支持成员操作的加入成员加入一个最低 MySQL Server 版本不支持成员操作的组,则加入时不会接收成员操作配置。在这种情况下,加入成员将自己的配置重置为默认值。

不支持成员操作的成员无法加入具有成员操作配置的组,因为其 MySQL Server 版本低于现有组成员运行的最低版本。

Performance Schema 表replication_group_member_actions列出了配置中可用的成员操作、触发它们的事件以及它们当前是否启用。成员操作的优先级从 1 到 100,较低的值首先执行。如果在执行成员操作时发生错误,则可以记录成员操作的失败,但否则忽略。如果认为成员操作的失败是关键的,则可以根据group_replication_exit_state_action系统变量指定的策略进行处理。

可以使用 Performance Schema 表replication_group_configuration_version查看的mysql.replication_group_configuration_version表记录了成员操作配置的当前版本。每当使用函数启用或禁用成员操作时,版本号都会递增。

group_replication_reset_member_actions函数只能在不属于任何组的服务器上使用。它将成员操作配置重置为默认设置,并将其版本号重置为 1。服务器必须可写(使用read_only系统变量设置为OFF),并安装了 Group Replication 插件。您可以使用此函数删除服务器在成为组的一部分时使用的成员操作配置,如果您打算将其用作没有成员操作或具有不同成员操作的独立服务器。

成员操作:mysql_disable_super_read_only_if_primary

成员操作mysql_disable_super_read_only_if_primary可以配置为使单主模式下的组在选举新主时保持在超级只读模式,以便该组仅接受复制事务,不接受来自客户端的直接写入。这种设置意味着当一个组的目的是为另一个组提供灾难容忍的次要备份时,您可以确保次要组与第一个组保持同步。

默认情况下,当选为主服务器时,超级只读模式在主服务器上被禁用,以便主服务器变为读写,并接受来自复制源服务器和客户端的更新。这是当成员操作mysql_disable_super_read_only_if_primary被启用时的情况,这是其默认设置。如果您使用group_replication_disable_member_action函数将操作设置为禁用,主服务器在选举后仍然保持在超级只读模式。在这种状态下,它不接受来自任何客户端的更新,甚至是具有CONNECTION_ADMINSUPER权限的用户。它仍然会接受由复制线程执行的更新。

20.5.2 重新启动组

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-restarting-group.html

Group Replication 旨在确保数据库服务持续可用,即使组成该组的某些服务器由于计划维护或意外问题而无法参与其中。只要剩余成员占据组的大多数,他们就可以选举新的主服务器并继续作为一个组运行。然而,如果复制组的每个成员都离开组,并且每个成员都通过STOP GROUP_REPLICATION语句或系统关闭停止了 Group Replication,那么该组现在只存在于理论上,作为成员上的一个配置。在这种情况下,要重新创建该组,必须像第一次启动一样通过引导启动。

首次引导组与第二次或后续引导组之间的区别在于,后者情况下,关闭的组的成员可能具有不同的事务集,取决于它们停止或失败的顺序。如果成员具有其他组成员上不存在的事务,则无法加入组。对于 Group Replication,这包括已提交和应用的事务,这些事务在gtid_executed GTID 集中,以及已经认证但尚未应用的事务,这些事务在group_replication_applier通道中。事务何时提交取决于为组设置的事务一致性级别(参见第 20.5.3 节,“事务一致性保证”)。然而,Group Replication 组成员永远不会删除已经认证的事务,这是成员承诺提交事务的声明。

因此,必须从最新的成员开始重新启动复制组,即执行最多事务并获得认证的成员。然后,事务较少的成员可以通过分布式恢复加入并赶上他们缺少的事务。不能假设组的最后已知主成员是组中最新的成员,因为比主成员关闭时间更晚的成员可能有更多的事务。因此,必须重新启动每个成员以检查事务,比较所有事务集,并确定最新的成员。然后可以使用该成员来引导组。

在每个成员关闭后,按照以下步骤安全地重新启动复制组。

  1. 依次对每个组成员执行以下步骤,顺序不限:

    1. 连接客户端到组成员。如果 Group Replication 尚未停止,请执行 STOP GROUP_REPLICATION 语句并等待 Group Replication 停止。

    2. 编辑 MySQL 服务器配置文件(通常在 Linux 和 Unix 系统上命名为 my.cnf,在 Windows 系统上命名为 my.ini),并设置系统变量 group_replication_start_on_boot=OFF。此设置防止 MySQL 服务器启动时启动 Group Replication,这是默认设置。

      如果无法在系统上更改该设置,则可以允许服务器尝试启动 Group Replication,这将失败,因为组已完全关闭且尚未引导。如果采用这种方法,请勿在此阶段在任何服务器上设置 group_replication_bootstrap_group=ON

    3. 启动 MySQL 服务器实例,并验证 Group Replication 尚未启动(或启动失败)。此阶段不要启动 Group Replication。

    4. 从组成员收集以下信息:

      • gtid_executed GTID 集的内容。您可以通过执行以下语句获取:

        mysql> SELECT @@GLOBAL.GTID_EXECUTED
        
      • group_replication_applier 通道上的已认证事务集。您可以通过执行以下语句获取:

        mysql> SELECT received_transaction_set FROM \
                performance_schema.replication_connection_status WHERE \
                channel_name="group_replication_applier";
        
  2. 当您从所有组成员收集了事务集后,比较它们以找出哪个成员具有最大的事务集,包括已执行的事务(gtid_executed)和已认证的事务(在 group_replication_applier 通道上)。您可以通过查看 GTID 手动执行此操作,或者使用存储函数比较 GTID 集,如 Section 19.1.3.8, “Stored Function Examples to Manipulate GTIDs” 中所述。

  3. 使用具有最大事务集的成员引导组,通过连接客户端到组成员并执行以下语句:

    mysql> SET GLOBAL group_replication_bootstrap_group=ON;
    mysql> START GROUP_REPLICATION;
    mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
    

    非常重要的是不要将设置 group_replication_bootstrap_group=ON 存储在配置文件中,否则当服务器再次重启时���将设置一个具有相同名称的第二个组。

  4. 要验证该组现在存在并包含此创始成员,请在引导它的成员上执行此语句:

    mysql> SELECT * FROM performance_schema.replication_group_members;
    
  5. 通过在每个成员上执行 START GROUP_REPLICATION 语句,以任意顺序将其他每个成员重新添加到组中:

    mysql> START GROUP_REPLICATION;
    
  6. 要验证每个成员是否已加入组,请在任何成员上执行此语句:

    mysql> SELECT * FROM performance_schema.replication_group_members;
    
  7. 当成员重新加入组后,如果您编辑了他们的配置文件以设置group_replication_start_on_boot=OFF,您可以再次编辑它们以设置ON(或者移除该系统变量,因为ON是默认值)。

20.5.3 事务一致性保证

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-consistency-guarantees.html

20.5.3.1 理解事务一致性保证

20.5.3.2 配置事务一致性保证

分布式系统(如 Group Replication)的一个重要影响是作为一个群体提供的一致性保证。换句话说,是分布在群体成员之间的事务全局同步的一致性。本节描述了 Group Replication 如何处理依赖于群体中发生的事件的一致性保证,以及如何最佳配置您的群体的一致性保证。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-understanding-consistency-guarantees.html

20.5.3.1 理解事务一致性保证

就分布式一致性保证而言,无论是在正常操作还是故障修复操作中,Group Replication 一直是一个最终一致性系统。这意味着一旦传入流量减慢或停止,所有组成员都具有相同的数据内容。与系统一致性相关的事件可以分为控制操作,无论是手动操作还是由故障自动触发;和数据流操作。

对于 Group Replication,可以根据一致性评估的控制操作包括:

  • 成员加入或离开,这在 Group Replication 的 Section 20.5.4, “分布式恢复” 和写保护中有所涵盖。

  • 网络故障,这由围栏模式涵盖。

  • 在单主组中,主故障切换,也可以是由 group_replication_set_as_primary() 触发的操作。

一致性保证和主故障切换

在单主组中,在次级节点被提升为主节点的主故障切换事件中,新的主节点可以立即对应用流量开放,无论复制积压数据有多大,或者可以限制访问直到积压数据被应用。

第一种方法是,在主故障后,组尽可能快地确保稳定的组成员资格,通过选举新的主节点,然后立即允许数据访问,同时仍在应用旧主节点的任何可能的积压数据。确保了写一致性,但在新的主节点应用积压数据时,读取可能暂时检索到陈旧数据。例如,如果客户端 C1 在旧主节点故障前刚写入 A=2 WHERE A=1,当客户端 C1 重新连接到新的主节点时,它可能读取到 A=1,直到新的主节点应用其积压数据并赶上旧主节点离开组的状态。

第二种选择是,在主故障后,系统确保稳定的组成员资格,并像第一种选择一样选举新的主节点,但在这种情况下,组等待新的主节点应用所有积压数据,然后才允许数据访问。这确保了在先前描述的情况下,当客户端 C1 重新连接到新的主节点时,它读取 A=2。然而,这样做的代价是,故障切换所需的时间与积压数据的大小成正比,在正确配置的组上应该很小。

在 MySQL 8.0.14 之前,没有办法配置故障切换策略,默认情况下可用性最大化,如第一种方法所述。在运行 MySQL 8.0.14 及更高版本的成员组中,您可以使用group_replication_consistency变量配置主故障切换期间成员提供的事务一致性保证级别。请参阅一致性对主选举的影响。

数据流操作

数据流与组一致性保证相关,因为读取和写入操作在组中执行,特别是当这些操作分布在所有成员之间时。数据流操作适用于组复制的两种模式:单主和多主,但为了更清晰地解释,本文仅限于单主模式。将传入的读取或写入事务分割到单主组成员的常规方式是将写入路由到主节点,并将读取均匀分布到从节点。由于组应该表现为单个实体,因此可以合理地期望主节点上的写入立即在从节点上可用。虽然组复制是使用实现 Paxos 算法的组通信系统(GCS)协议编写的,但组复制的某些部分是异步的,这意味着数据会异步应用到从节点。这意味着客户端 C2 可以在主节点上写入B=2 WHERE B=1,立即连接到从节点并读取B=1。这是因为从节点仍在应用积压数据,并且尚未应用主节点应用的事务。

事务同步点

您可以根据希望在组中同步事务的时间点配置组的一致性保证。为了帮助您理解概念,本节将简化跨组同步事务的时间点为读取操作时或写入操作时。如果在读取时同步数据,则当前客户端会等待直到给定时间点,即所有先前的更新事务都已应用,然后才能开始执行。使用这种方法,只有此会话受到影响,所有其他并发数据操作不受影响。

如果在写入时同步数据,则写入会话会等待直到所有从节点写入其数据。组复制使用写入的总顺序,因此这意味着等待这个和所有在从节点队列中的先前写入被应用。因此,当使用此同步点时,写入会话等待所有从节点队列被应用。

任何替代方案都确保在描述的客户端 C2 的情况下,即使立即连接到辅助服务器,也始终读取B=2。每种替代方案都有其优点和缺点,这些直接与你的系统工作负载相关。以下示例描述了不同类型的工作负载,并建议哪种同步点是适当的。

想象以下情况:

  • 你希望负载均衡你的读取操作,而不需要在从哪个服务器读取时部署额外的限制,以避免读取过时数据,组写入比组读取要少得多。

  • 如果你有一个主要是只读数据的组,你希望读写事务在提交后到处都被应用,这样后续的读取都是在包含最新写入的最新数据上进行的。这确保你不必为每个只读事务支付同步成本,而只需为读写事务支付。

在这些情况下,你应该选择在写入时进行同步。

想象以下情况:

  • 你希望负载均衡你的读取操作,而不需要在从哪个服务器读取时部署额外的限制,以避免读取过时数据,组写入比组读取要常见得多。

  • 你希望你的工作负载中的特定事务始终从组中读取最新数据,例如每当敏感数据更新时(例如文件的凭据或类似数据),你希望强制读取检索到最新值。

在这些情况下,你应该选择在读取时进行同步。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-consistency-guarantees.html

20.5.3.2 配置事务一致性保证

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

  • 如何选择一致性级别

  • 一致性级别的影响

  • 一致性对主选举的影响

  • 一致性规则下允许的查询

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

  • 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 事务就会被应用到所有地方。您的应用程序可以使用此模式来确保后续读取获取包括最新写入的最新数据。通过仅在 RW 事务上使用同步,可以减少每个 RO 事务上的同步开销。此一致性级别还包括BEFORE_ON_PRIMARY_FAILOVER提供的一致性保证。

  • BEFORE_AND_AFTER

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

BEFOREBEFORE_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’

总结一下,你不需要以特定的一致性级别运行所有事务,特别是如果只有一些事务实际上需要它。

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

一致性级别的影响

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

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

一致性级别AFTERBEFORE_AND_AFTER对在其他成员上执行的并发事务确实会产生副作用。如果具有EVENTUAL一致性级别的事务在执行具有AFTERBEFORE_AND_AFTER的事务时开始,其他成员的事务将等待,直到AFTER事务在该成员上提交,即使其他成员的事务具有EVENTUAL一致性级别。换句话说,AFTERBEFORE_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成员上使用一致性级别BEFOREAFTERBEFORE_AND_AFTER,尝试在其他状态的成员上使用它们会导致会话错误。

一致性级别不是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 时,您选择优先考虑一致性而不是可用性,因为每当选举新的主要成员时,读写操作都会被保留。这是在配置组时必须考虑的权衡。还应记住,如果流量控制正常工作,backlog 应该是最小的。请注意,更高的一致性级别 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 一致性级别时,虽然所有写操作都被保留,但并非所有读操作都被阻塞,以确保您仍然可以在升级后的服务器应用 backlog 时进行检查。这对于调试、监控、可观察性和故障排除非常有用。一些不修改数据的查询是允许的,例如以下内容:

  • SHOW 语句 - 从 MySQL 8.0.27 开始,此处仅限于不依赖于数据,仅依赖于状态和配置的语句,如下所列

  • SET 语句

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

  • EMPTY 语句

  • USE 语句

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

  • 使用针对 infoschema 数据库中的 PROCESSLIST 表的 SELECT 语句

  • 不使用表或可加载函数的 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,SHOW RELAYLOG EVENTS

20.5.4 分布式恢复

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-distributed-recovery.html

20.5.4.1 用于分布式恢复的连接

20.5.4.2 用于分布式恢复的克隆

20.5.4.3 配置分布式恢复

20.5.4.4 分布式恢复的容错性

20.5.4.5 分布式恢复的工作原理

每当成员加入或重新加入复制组时,它必须赶上在其加入之前或离开期间组成员应用的事务。这个过程称为分布式恢复。

加入成员首先通过检查其group_replication_applier通道的中继日志,查看组中已接收但尚未应用的任何事务。如果加入成员以前曾在组中,它可能会发现在离开之前未应用的事务,这种情况下会将其作为第一步应用。新加入组的成员没有任何需要应用的事务。

在此之后,加入成员连接到在线现有成员以进行状态传输。加入成员传输了在其加入组之前或离开期间发生的所有事务,这些事务由现有成员(称为捐赠者)提供。接下来,加入成员应用了在此状态传输过程中组中发生的事务。当此过程完成时,加入成员已经赶上了组中的其余服务器,并开始正常参与组中的活动。

组复制在分布式恢复期间使用这些方法的组合进行状态传输:

  • 使用克隆插件的功能进行远程克隆操作,该功能从 MySQL 8.0.17 起可用。要启用此状态传输方法,必须在组成员和加入成员上安装克隆插件。组复制自动配置所需的克隆插件设置,并管理远程克隆操作。

  • 从捐赠者的二进制日志复制并在加入成员上应用事务。此方法使用一个名为group_replication_recovery的标准异步复制通道,在捐赠者和加入成员之间建立。

在加入成员上发出START GROUP_REPLICATION后,组复制会自动选择这些方法的最佳组合进行状态转移。为此,组复制会检查哪些现有成员适合作为捐赠者,加入成员需要从捐赠者那里获取多少事务,以及是否在任何组成员的二进制日志文件中不再存在任何必需的事务。如果加入成员与适当的捐赠者之间的事务差距很大,或者某些必需的事务不在任何捐赠者的二进制日志文件中,组复制将开始进行远程克隆操作的分布式恢复。如果事务差距不大,或者未安装克隆插件,则组复制直接进行从捐赠者的二进制日志进行状态转移。

  • 在远程克隆操作期间,加入成员上的现有数据将被删除,并替换为捐赠者的数据副本。当远程克隆操作完成并加入成员重新启动时,将执行从捐赠者的二进制日志进行状态转移,以获取在远程克隆操作进行时组应用的事务。

  • 在从捐赠者的二进制日志进行状态转移期间,加入成员复制并应用所需的事务从捐赠者的二进制日志中,按照接收到的事务逐个应用,直到二进制日志记录加入成员加入组的点(视图更改事件)。在此过程中,加入成员缓冲组应用的新事务。当从二进制日志的状态转移完成时,加入成员应用缓冲事务。

当加入成员与组的所有事务保持最新时,它被声明为在线,并可以作为正常成员参与组,并且分布式恢复完成。

提示

从二进制日志进行状态转移是组复制的分布式恢复的基本机制,如果您的复制组中的捐赠者和加入成员未设置为支持克隆,则这是唯一可用的选项。由于从二进制日志进行状态转移是基于经典的异步复制,如果加入组的服务器根本没有组的数据,或者具有来自非常旧的备份镜像的数据,可能需要很长时间。因此,在将服务器添加到组之前,建议您通过传输一个相当新的服务器快照来设置具有组数据的服务器。这样可以最大程度地减少分布式恢复所需的时间,并减少对捐赠者服务器的影响,因为它们需要保留和传输更少的二进制日志文件。

译文:dev.mysql.com/doc/refman/8.0/en/group-replication-distributed-recovery-connections.html

20.5.4.1 分布式恢复的连接

当一个加入成员在分布式恢复期间连接到在线现有成员进行状态传输时,加入成员在连接上充当客户端,而现有成员充当服务器。当通过这个连接从捐赠者的二进制日志进行状态传输(使用异步复制通道group_replication_recovery)时,加入成员充当副本,而现有成员充当源。当远程克隆操作在这个连接上进行时,加入成员充当接收者,而现有成员充当捐赠者。适用于这些角色的配置设置在 Group Replication 上下文之外也适用于 Group Replication,除非它们被 Group Replication 特定的配置设置或行为所覆盖。

现有成员为分布式恢复向加入成员提供的连接并不是 Group Replication 用于组内在线成员之间通信的连接。

  • Group Replication 的组通信引擎(XCom,一种 Paxos 变体)用于远程 XCom 实例之间的 TCP 通信的连接由group_replication_local_address系统变量指定。这个连接用于在线成员之间的 TCP/IP 消息。与本地实例的通信通过使用共享内存的输入通道进行。

  • 对于分布式恢复,直到 MySQL 8.0.20,组成员向加入成员提供他们的标准 SQL 客户端连接,由 MySQL Server 的hostnameport系统变量指定。如果report_port系统变量指定了替代端口号,则使用该端口号。

  • 从 MySQL 8.0.21 开始,组成员可以向加入成员提供一组专用客户端连接作为分布式恢复端点的替代列表,允许您单独控制分布式恢复流量,而不是由成员的常规客户端用户连接。您可以使用group_replication_advertise_recovery_endpoints系统变量指定此列表,并在加入组时成员将其分布式恢复端点列表传输给组。默认情况下,成员继续像早期版本一样提供标准 SQL 客户端连接。

重要提示

如果加入成员无法使用由 MySQL Server 的hostname系统变量定义的主机名正确识别其他成员,则分布式恢复可能会失败。建议运行 MySQL 的操作系统具有经过正确配置的唯一主机名,可以使用 DNS 或本地设置。服务器用于 SQL 客户端连接的主机名可以在性能模式表replication_group_membersMember_host列中验证。如果多个组成员外部化由操作系统设置的默认主机名,那么加入成员可能无法将其解析为正确的成员地址并无法连接进行分布式恢复。在这种情况下,您可以使用 MySQL Server 的report_host系统变量为每个服务器配置一个唯一的主机名来外部化。

加入成员建立分布式恢复连接的步骤如下:

  1. 当成员加入组时,它使用其group_replication_group_seeds系统变量中包含的种子成员列表中的一个连接,最初使用该列表中指定的group_replication_local_address连接。种子成员可能是组的子集。

  2. 通过此连接,种子成员使用 Group Replication 的成员服务向加入成员提供了一个在线组中所有成员的列表,以视图的形式呈现。成员信息包括每个成员提供的用于分布式恢复的分布式恢复端点或标准 SQL 客户端连接的详细信息。

  3. 加入成员从此列表中选择一个适合的组成员作为其分布式恢复的捐赠者,遵循第 20.5.4.4 节“分布式恢复的容错”中描述的行为。

  4. 然后,加入成员尝试使用捐赠者广告的分布式恢复端点连接到捐赠者,依次尝试列表中指定的顺序。如果捐赠者没有提供端点,则加入成员尝试使用捐赠者的标准 SQL 客户端连接。连接的 SSL 要求如第 20.5.4.1.4 节“分布式恢复的 SSL 和身份验证”中描述的group_replication_recovery_ssl_*选项所指定。

  5. 如果加入成员无法连接到所选的提供者,它将尝试与其他适当的提供者重试,遵循 第 20.5.4.4 节,“分布式恢复的容错性” 中描述的行为。请注意,如果加入成员在不建立连接的情况下耗尽了广告端点列表,则不会回退到提供者的标准 SQL 客户端连接,而是切换到另一个提供者。

  6. 当加入成员与提供者建立分布式恢复连接时,它将使用该连接进行状态传输,如 第 20.5.4 节,“分布式恢复” 中所述。用于连接的主机和端口在加入成员的日志中显示。请注意,如果使用远程克隆操作,当加入成员在操作结束时重新启动时,它将与新的提供者建立连接,以从二进制日志进行状态传输。这可能是与用于远程克隆操作的原始提供者不同的成员的连接,或者可能是与原始提供者的不同连接。无论如何,分布式恢复过程都将像在原始提供者的情况下一样继续。

20.5.4.1.1 选择分布式恢复端点的地址

group_replication_advertise_recovery_endpoints 系统变量提供的 IP 地址作为分布式恢复端点不需要为 MySQL Server 配置(即,它们不需要由 admin_address 系统变量指定或在 bind_address 系统变量的列表中)。它们必须分配给服务器。使用的任何主机名必须解析为本地 IP 地址。可以使用 IPv4 和 IPv6 地址。

为了 MySQL Server 配置分布式恢复端点所提供的端口必须通过 portreport_portadmin_port 系统变量指定。服务器必须在这些端口上监听 TCP/IP 连接。如果指定了 admin_port,则分布式恢复的复制用户需要 SERVICE_CONNECTION_ADMIN 权限才能连接。选择 admin_port 可以将分布式恢复连接与常规 MySQL 客户端连接分开。

加入的成员依次尝试列表中指定的每个端点。如果group_replication_advertise_recovery_endpoints设置为DEFAULT而不是端点列表,则提供标准的 SQL 客户端连接。请注意,标准的 SQL 客户端连接不会自动包含在分布式恢复端点列表中,并且不会作为备用方案提供,如果捐赠者的端点列表在没有连接的情况下耗尽。如果您希望将标准的 SQL 客户端连接作为多个分布式恢复端点之一提供,您必须在由group_replication_advertise_recovery_endpoints指定的列表中显式包含它。您可以将其放在最后一位,以便作为连接的最后手段。

一个组成员的分布式恢复端点(或标准的 SQL 客户端连接,如果没有提供端点)不需要添加到由group_replication_ip_allowlist(从 MySQL 8.0.22 开始)或group_replication_ip_whitelist地址。加入的成员必须通过允许列表允许的初始连接到组,以便检索分布式恢复的地址或地址。

当设置系统变量并发出START GROUP_REPLICATION语句时,您列出的分布式恢复端点将得到验证。如果列表无法正确解析,或者如果主机上的任何端点无法访问,因为服务器没有在其上监听,Group Replication 将记录错误并且不会启动。

20.5.4.1.2 分布式恢复的压缩

从 MySQL 8.0.18 开始,您可以选择通过从捐赠者的二进制日志进行状态传输的方法为分布式恢复配置压缩。压缩可以使分布式恢复受益,特别是在网络带宽有限且捐赠者必须向加入成员传输许多事务时。group_replication_recovery_compression_algorithmsgroup_replication_recovery_zstd_compression_level系统变量配置允许的压缩算法,以及在从捐赠者的二进制日志进行状态传输时使用的zstd压缩级别。有关更多信息,请参见第 6.2.8 节,“连接压缩控制”。

请注意,这些压缩设置不适用于远程克隆操作。当远程克隆操作用于分布式恢复时,克隆插件的clone_enable_compression设置适用。

20.5.4.1.3 分布式恢复的复制用户

分布式恢复需要一个具有正确权限的复制用户,以便 Group Replication 可以建立直接成员间的复制通道。复制用户还必须具有正确权限,以在捐赠者上充当远程克隆操作的克隆用户。在每个组成员上进行分布式恢复时必须使用相同的复制用户。有关设置此复制用户的说明,请参见第 20.2.1.3 节,“分布式恢复的用户凭据”。有关保护复制用户凭据的说明,请参见第 20.6.3.1 节,“分布式恢复的安全用户凭据”。

20.5.4.1.4 分布式恢复的 SSL 和身份验证

分布式恢复的 SSL 配置与正常组通信的 SSL 配置是分开的,由服务器的 SSL 设置和group_replication_ssl_mode系统变量确定。对于分布式恢复连接,专用的 Group Replication 分布式恢复 SSL 系统变量可用于配置专门用于分布式恢复的证书和密码。

默认情况下,分布式恢复连接不使用 SSL。要激活它,请设置group_replication_recovery_use_ssl=ON,并按照 Section 20.6.3, “Securing Distributed Recovery Connections”中描述的方式配置 Group Replication 分布式恢复 SSL 系统变量。您需要设置一个用于 SSL 的复制用户。

当配置分布式恢复使用 SSL 时,Group Replication 会将此设置应用于远程克隆操作,以及从捐赠者的二进制日志进行状态传输。Group Replication 会自动配置克隆 SSL 选项(clone_ssl_caclone_ssl_cert,和clone_ssl_key)的设置,以匹配相应的 Group Replication 分布式恢复选项(group_replication_recovery_ssl_cagroup_replication_recovery_ssl_cert,和group_replication_recovery_ssl_key)的设置。

如果您没有为分布式恢复使用 SSL(因此group_replication_recovery_use_ssl设置为OFF),并且 Group Replication 的复制用户帐户使用caching_sha2_password插件(这是 MySQL 8.0 中的默认设置)或sha256_password插件进行身份验证,则会使用 RSA 密钥对进行密码交换。在这种情况下,要么使用group_replication_recovery_public_key_path系统变量指定 RSA 公钥文件,要么使用group_replication_recovery_get_public_key系统变量从源请求公钥,如 Section 20.6.3.1.1, “Replication User With The Caching SHA-2 Authentication Plugin”中所述。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-cloning.html

20.5.4.2 分布式恢复的克隆

MySQL Server 的克隆插件从 MySQL 8.0.17 开始提供。如果要在组中使用远程克隆操作进行分布式恢复,必须事先设置现有成员和加入成员以支持此功能。如果不想在组中使用此功能,请不要设置,此时组复制仅使用来自二进制日志的状态传输。

要使用克隆,至少一个现有组成员和加入成员必须事先设置以支持远程克隆操作。最低要求是,在捐赠者和加入成员上安装克隆插件,为分布式恢复的复制用户授予BACKUP_ADMIN权限,并将group_replication_clone_threshold系统变量设置为适当的级别。为确保捐赠者的最大可用性,建议设置所有当前和未来的组成员以支持远程克隆操作。

请注意,远程克隆操作会在从捐赠者传输数据之前,从加入成员中删除用户创建的表空间和数据。如果操作在进行中停止,加入成员可能会留下部分数据或没有数据。这可以通过重新尝试远程克隆操作来修复,组复制会自动执行此操作。

20.5.4.2.1 克隆的先决条件

要设置和配置克隆插件的完整说明,请参阅第 7.6.7 节,“克隆插件”。有关远程克隆操作的详细先决条件,请参阅第 7.6.7.3 节,“克隆远程数据”。对于组复制,请注意以下关键点和差异:

  • 捐赠者(现有组成员)和接收者(加入成员)必须安装并激活克隆插件。有关如何执行此操作的说明,请参阅第 7.6.7.1 节,“安装克隆插件”。

  • 捐赠者和接收者必须运行在相同的操作系统上,并且必须具有相同的 MySQL Server 版本系列。因此,对于运行不同次要 MySQL Server 版本的组,如 MySQL 8.0 和 8.4,克隆不适用。

    在 MySQL 8.0.37 之前,克隆要求捐赠者和接收者是相同的点版本,如果捐赠者或接收者是 MySQL 8.0.36 或更早版本,则仍然适用此限制。

  • 捐赠者和接收者必须安装并激活组复制插件,捐赠者上激活的任何其他插件(如密钥环插件)也必须在接收者上激活。

  • 如果分布式恢复配置为使用 SSL(group_replication_recovery_use_ssl=ON),组复制会将此设置应用于远程克隆操作。组复制会自动配置克隆 SSL 选项的设置(clone_ssl_caclone_ssl_certclone_ssl_key),以匹配您对应的组复制分布式恢复选项的设置(group_replication_recovery_ssl_cagroup_replication_recovery_ssl_certgroup_replication_recovery_ssl_key)。

  • 在加入复制组的过程中,您无需在clone_valid_donor_list系统变量中设置有效捐赠者列表。组复制会在从现有组成员中选择捐赠者后自动为您配置此设置。请注意,远程克隆操作使用服务器的 SQL 协议主机名和端口。

  • 克隆插件有许多系统变量来管理远程克隆操作的网络负载和性能影响。组复制不会配置这些设置,因此您可以查看并设置它们,或者允许它们使用默认设置。请注意,当远程克隆操作用于分布式恢复时,克隆插件的clone_enable_compression设置适用于操作,而不是组复制的压缩设置。

  • 为了在接收端调用远程克隆操作,组复制使用内部的mysql.session用户,该用户已经具有CLONE_ADMIN权限,因此您无需设置此权限。

  • 作为远程克隆操作的捐赠者上的克隆用户,Group Replication 使用您为分布式恢复设置的复制用户(在 Section 20.2.1.3, “User Credentials For Distributed Recovery”中介绍)。因此,您必须在支持克隆的所有组成员上为此复制用户授予BACKUP_ADMIN权限。在为 Group Replication 配置加入成员时,还必须为复制用户授予权限,因为它们在加入组后可以充当捐赠者。在每个组成员上为复制用户授予此权限,您可以在禁用二进制日志记录的每个组成员上单独发出此语句,或者在启用二进制日志记录的一个组成员上发出:

    GRANT BACKUP_ADMIN ON *.* TO *rpl_user*@'%';
    
  • 如果您使用START GROUP_REPLICATION在服务器上指定复制用户凭据,而该服务器先前使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO提供用户凭据,请确保在进行任何远程克隆操作之前从复制元数据存储库中删除用户凭据。还要确保group_replication_start_on_boot=OFF在加入成员上设置。有关说明,请参见 Section 20.6.3, “Securing Distributed Recovery Connections”。如果不取消用户凭据,则在远程克隆操作期间,这些凭据将传输到加入成员。然后,group_replication_recovery通道可能会意外地使用存储的凭据在原始成员或从原始成员克隆的成员上启动。服务器启动时(包括远程克隆操作后)自动启动 Group Replication 将使用存储的用户凭据,如果操作员未在START GROUP_REPLICATION命令中指定分布式恢复凭据,则也会使用这些凭据。

20.5.4.2.2 克隆门槛

当组成员已经设置支持克隆时,group_replication_clone_threshold 系统变量指定了一个阈值,以事务数量表示,用于在分布式恢复中使用远程克隆操作。如果捐赠者的事务和加入成员的事务之间的差距大于这个数字,当技术上可能时,将使用远程克隆操作进行状态传输到加入成员。Group Replication 根据现有组成员的 gtid_executed 集合计算是否已超过阈值。在存在较大事务差距的情况下使用远程克隆操作,可以让您向组中添加新成员,而无需事先手动将组的数据传输到服务器,并且还可以使非常过时的成员更有效地追赶。

group_replication_clone_threshold Group Replication 系统变量的默认设置非常高(GTID 中事务的最大允许序列号),因此在可能从二进制日志进行状态传输的地方,它有效地停用了克隆。要使 Group Replication 在更合适的情况下选择远程克隆操作进行状态传输,请设置系统变量以指定一个事务数量作为您希望进行克隆的事务差距的上限。

警告

在活动组中不要使用低设置的 group_replication_clone_threshold。如果在远程克隆操作正在进行时组中发生超过阈值的事务数量,那么加入成员在重新启动后会再次触发远程克隆操作,并且可能会无限继续这样做。为避免这种情况,请确保将阈值设置为高于您预期在远程克隆操作所需时间内组中可能发生的事务数量。

集群复制尝试执行远程克隆操作,无论您的阈值如何,当从捐赠者的二进制日志中无法进行状态转移时,例如因为加入成员所需的事务在任何现有组成员的二进制日志中都不可用时。集群复制根据现有组成员的gtid_purged集合来识别这一点。当任何成员的二进制日志文件中没有所需的事务时,您不能使用group_replication_clone_threshold系统变量来停用克隆,因为在这种情况下,克隆是将数据传输到加入成员的唯一选择。

20.5.4.2.3 克隆操作

当组成员和加入成员设置为进行克隆时,集群复制会为您管理远程克隆操作。远程克隆操作可能需要一些时间才能完成,具体取决于数据的大小。有关监视过程的信息,请参见第 7.6.7.10 节,“监视克隆操作”。

注意

当状态转移完成时,集群复制会重新启动加入成员以完成该过程。如果在加入成员上设置了group_replication_start_on_boot=OFF,例如因为您在START GROUP_REPLICATION语句中指定了复制用户凭据,那么您必须在此重新启动后再次手动发出START GROUP_REPLICATION。如果group_replication_start_on_boot=ON和启动集群复制所需的其他设置是在配置文件中设置或使用SET PERSIST语句设置的,则您无需干预,该过程将自动继续以使加入成员在线。

如果远程克隆过程花费很长时间,在 MySQL 8.0.22 之前的版本中,可能会出现在此期间为组积累的证书信息集合过大而无法传输给加入成员的情况。在这种情况下,加入成员会记录错误消息并且不会加入组。从 MySQL 8.0.22 开始,组复制以不同的方式管理已应用事务的垃圾收集过程,以避免这种情况发生。在早期版本中,如果您看到此错误,请在远程克隆操作完成后等待两分钟,以便进行一轮垃圾收集以减小组的证书信息大小。然后在加入成员上发出以下语句,以使其停止尝试应用先前的证书信息:

RESET SLAVE FOR CHANNEL group_replication_recovery;
Or from MySQL 8.0.22:
RESET REPLICA FOR CHANNEL group_replication_recovery;

远程克隆操作会将存储在表中的设置从捐赠者克隆到接收者,以及数据。组复制管理与组复制通道相关的设置。在配置文件中持久化的组复制成员设置,如组复制本地地址,不会被克隆,也不会在加入成员时更改。组复制还保留与 SSL 使用相关的通道设置,因此这些设置对于每个成员都是独一无二的。

如果捐赠者用于group_replication_recovery复制通道的复制用户凭据已使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句存储在复制元数据存储库中,则在克隆后将其传输到并由加入成员使用,并且必须在那里有效。使用存储的凭据,通过远程克隆操作接收状态转移的所有组成员因此自动接收用于分布式恢复的复制用户和密码。如果在START GROUP_REPLICATION语句中指定了复制用户凭据,则这些凭据用于启动远程克隆操作,但在克隆后不会被传输到并由加入成员使用。如果不希望将凭据传输给新加入者并记录在那里,请确保在进行远程克隆操作之前取消设置它们,如第 20.6.3 节“保护分布式恢复连接”中所述,并使用START GROUP_REPLICATION来代替提供它们。

如果使用PRIVILEGE_CHECKS_USER帐户来帮助保护复制应用程序(请参阅 Section 19.3.3.2, “Group Replication 通道的权限检查”),从 MySQL 8.0.19 开始,将从捐赠者克隆PRIVILEGE_CHECKS_USER帐户和相关设置到加入的成员。如果设置加入的成员在启动时启动 Group Replication,则自动在适当的复制通道上使用该帐户进行权限检查。(在 MySQL 8.0.18 中,由于一些限制,建议不要在 Group Replication 通道中使用PRIVILEGE_CHECKS_USER帐户。)

20.5.4.2.4 其他目的的克隆

Group Replication 启动并管理分布式恢复的克隆操作。已设置为支持克隆的组成员也可以参与用户手动启动的克隆操作。例如,您可能希望通过从组成员作为捐赠者进行克隆来创建一个新的服务器实例,但您不希望新的服务器实例立即加入组,甚至可能永远不加入。

在支持克隆的所有版本中,您可以手动启动涉及 Group Replication 已停止的组成员的克隆操作。请注意,由于克隆要求捐赠者和接收者上的活动插件必须匹配,因此即使您不打算使服务器实例加入组,Group Replication 插件也必须在另一个服务器实例上安装并激活。您可以通过发出以下语句来安装插件:

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

在 MySQL 8.0.20 之前的版本中,如果克隆操作涉及正在运行 Group Replication 的组成员,则无法手动启动克隆操作。从 MySQL 8.0.20 开始,您可以这样做,前提是克隆操作不会删除并替换接收方的数据。因此,启动克隆操作的语句必须包含DATA DIRECTORY子句,如果 Group Replication 正在运行。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-tuning-recovery.html

20.5.4.3 配置分布式恢复

Group Replication 的分布式恢复过程的几个方面可以配置以适应您的系统。

连接尝试次数

对于从二进制日志进行状态传输,Group Replication 限制了加入成员在尝试连接到供体池中的供体时所做的尝试次数。如果达到连接重试限制而没有成功连接,则分布式恢复过程将以错误终止。请注意,此限制指定了加入成员尝试连接到供体的总次数。例如,如果有 2 个组成员是适当的供体,并且连接重试限制设置为 4,加入成员在达到限制之前对每个供体进行 2 次连接尝试。

默认连接重试限制为 10。您可以使用group_replication_recovery_retry_count系统变量来配置此设置。以下命令将最大连接尝试次数设置为 5:

mysql> SET GLOBAL group_replication_recovery_retry_count= 5;

对于远程克隆操作,不适用此限制。Group Replication 仅尝试与每个适当的供体进行一次连接,然后开始尝试从二进制日志进行状态传输。

连接尝试的休眠间隔

对于从二进制日志进行状态传输,group_replication_recovery_reconnect_interval系统变量定义了分布式恢复过程在尝试连接到供体之间应该休眠多长时间。请注意,分布式恢复在每次供体连接尝试后不会休眠。由于加入成员正在连接到不同的服务器而不是重复连接到同一个服务器,它可以假设影响服务器 A 的问题不会影响服务器 B。因此,分布式恢复仅在经过所有可能的供体后暂停。一旦加入组的服务器对组中的每个适当的供体都尝试连接了一次,分布式恢复过程将休眠,时间由group_replication_recovery_reconnect_interval系统变量配置。例如,如果有 2 个组成员是适当的供体,并且连接重试限制设置为 4,加入成员对每个供体进行一次连接尝试,然后休眠连接重试间隔,然后对每个供体进行一次进一步的连接尝试,直到达到限制。

默认连接重试间隔为 60 秒,您可以动态更改此值。以下命令将分布式恢复捐赠者连接重试间隔设置为 120 秒:

mysql> SET GLOBAL group_replication_recovery_reconnect_interval= 120;

对于远程克隆操作,此间隔不适用。在开始尝试从二进制日志进行状态转移之前,Group Replication 仅对每个适当的捐赠者进行一次连接尝试。

在线标记加入成员

当分布式恢复成功完成从捐赠者到加入成员的状态转移后,加入成员可以在组中标记为在线并准备参与。默认情况下,在加入成员接收并应用了其缺失的所有事务后才会执行此操作。可选地,您可以允许在加入成员接收并认证(即完成冲突检测)其缺失的所有事务后,但在应用它们之前将其标记为在线。如果您想这样做,请使用group_replication_recovery_complete_at系统变量来指定替代设置TRANSACTIONS_CERTIFIED

dev.mysql.com/doc/refman/8.0/en/group-replication-distributed-recovery-fault.html

20.5.4.4 分布式恢复的容错性

Group Replication 的分布式恢复过程具有多项内置措施,以确保在过程中出现任何问题时的容错性。

从当前视图中的适当在线组成员列表中随机选择分布式恢复的捐赠者。选择随机捐赠者意味着当多个成员进入组时,同一服务器不会被多次选择的机会很大。从 MySQL 8.0.17 开始,对于从二进制日志进行状态转移,加入者只选择运行低于或等于自身的 MySQL Server 补丁版本的捐赠者。对于早期版本,所有在线成员都可以成为捐赠者。对于远程克隆操作,加入者只选择与自身运行相同补丁版本的捐赠者。请注意,当加入成员在操作结束时重新启动时,它会与新的捐赠者建立连接,以从二进制日志进行状态转移,这可能是与用于远程克隆操作的原始捐赠者不同的成员。

在以下情况下,Group Replication 检测到分布式恢复中的错误,自动切换到新的捐赠者,并重试状态转移:

  • 连接错误 - 存在身份验证问题或与候选捐赠者建立连接的其他问题。

  • 复制错误 - 用于从二进制日志进行状态转移的复制线程之一(接收器或应用程序线程)失败。由于此状态转移方法使用现有的 MySQL 复制框架,因此可能会出现一些瞬态错误导致接收器或应用程序线程出错。

  • 远程克隆操作错误 - 远程克隆操作失败或在完成之前停止。

  • 捐赠者离开组 - 捐赠者离开组,或者在状态转移正在进行时,在捐赠者上停止 Group Replication。

Performance Schema 表replication_applier_status_by_worker显示导致最后一次重试失败的错误。在这些情况下,错误后的新连接将尝试与新的候选捐赠者建立连接。在错误事件中选择不同的捐赠者意味着新的候选捐赠者可能不会有相同的错误。如果安装了克隆插件,Group Replication 首先尝试与每个适当的在线支持克隆的捐赠者进行远程克隆操作。如果所有这些尝试失败,Group Replication 将尝试依次从所有适当的捐赠者进行二进制日志状态转移,如果可能的话。

警告

对于远程克隆操作,接收方(加入成员)上的用户创建的表空间和数据在远程克隆操作开始传输数据之前被删除。如果远程克隆操作开始但未完成,加入成员可能会留下部分原始数据文件集,或者没有用户数据。如果在数据完全克隆之前停止克隆操作,捐赠者传输的数据将从接收方中删除。Group Replication 会自动重试克隆操作,以修复这种情况。

在以下情况下,分布式恢复过程无法完成,加入成员将离开组:

  • 清除的事务 - 加入成员需要的事务不在任何在线组成员的二进制日志文件中,并且数据无法通过远程克隆操作获取(因为未安装克隆插件,或者尝试了所有可能的捐赠者但失败)。因此,加入成员无法赶上组的进度。

  • 额外的事务 - 加入成员已经包含一些组中不存在的事务。如果进行了远程克隆操作,这些事务将被删除和丢失,因为加入成员上的数据目录被擦除。如果进行了从捐赠者的二进制日志进行状态传输,这些事务可能会与组的事务发生冲突。有关处理此情况的建议,请参阅额外事务。

  • 连接重试限制已达到 - 加入成员已经尝试了连接重试限制允许的所有连接尝试。您可以使用group_replication_recovery_retry_count系统变量进行配置(参见第 20.5.4.3 节,“配置分布式恢复”)。

  • 没有更多的捐赠者 - 加入成员已经尝试了每个在线支持克隆的捐赠者进行远程克隆操作(如果安装了克隆插件),然后尝试了每个适当的在线捐赠者进行二进制日志的状态传输,如果可能的话。

  • 加入成员离开组 - 加入成员离开组或在状态传输进行中时,加入成员上的 Group Replication 停止。

如果加入成员意外离开组,因此在上述任何情况下(除最后一种情况外),它将执行group_replication_exit_state_action系统变量指定的操作。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-view-changes.html

20.5.4.5 分布式恢复的工作原理

当 Group Replication 的分布式恢复过程从二进制日志中执行状态传输时,为了使加入的成员与捐赠者在特定时间点上同步,加入的成员和捐赠者使用 GTIDs(参见 Section 19.1.3, “Replication with Global Transaction Identifiers”)。然而,GTIDs 只提供了加入成员缺失的事务信息。它们并不能帮助标记加入群组的服务器必须追赶到的特定时间点,也不能传递认证信息。这是二进制日志视图标记的工作,它们标记了二进制日志流中的视图更改,并且包含额外的元数据信息,为加入成员提供缺失的与认证相关的数据。

本主题解释了视图更改的作用以及视图更改标识符,以及执行从二进制日志中进行状态传输的步骤。

视图和视图更改

一个视图对应于在当前配置中积极参与的一组成员,换句话说就是在特定时间点。他们在群组中正常运行并在线。

视图更改发生在群组配置发生修改时,比如成员加入或离开。任何群组成员变更都会导致独立的视图更改,同时在同一逻辑时间点向所有成员通信。

视图标识符唯一标识一个视图。每当视图更改发生时,它就会生成。

在群组通信层,视图更改及其相关的视图标识符标记了成员加入之前和之后交换的数据之间的边界。这个概念通过二进制日志事件实现:"视图更改日志事件"(VCLE)。视图标识符被记录下来,以划分在群组成员身份发生更改之前和之后传输的事务。

视图标识符本身由两部分构成:一个随机生成的部分和一个单调递增的整数。随机生成的部分在创建组时生成,并在组中至少有一个成员时保持不变。整数在每次视图更改发生时递增。使用这两个不同的部分使视图标识符能够识别由成员加入或离开引起的增量组更改,并且能够识别所有成员离开组导致的完全组关闭的情况,因此不会留下任何关于组处于何种视图的信息。在组从一开始创建时随机生成标识符的部分确保二进制日志中的数据标记保持唯一,并且在完全组关闭后不会重复使用相同的标识符,因为这将导致未来的分布式恢复出现问题。

开始:稳定组

所有服务器都在线并处理来自组的传入交易。一些服务器可能在复制交易方面稍有落后,但最终它们会收敛。该组充当一个分布式和复制的数据库。

图 20.8 稳定组

服务器 S1、S2 和 S3 是组的成员。它们的二进制日志中最近的项目是交易 T20。

视图更改:成员加入

每当新成员加入组,因此执行视图更改时,每个在线服务器都会将视图更改日志事件排队等待执行。这是因为在视图更改之前,服务器上可以排队应用的多个交易,因此这些属于旧视图。在它们之后排队视图更改事件可以保证正确标记此事件发生的时间。

与此同时,加入的成员从在线服务器列表中选择一个适当的捐赠者,如成员服务通过视图抽象所述。一个成员在视图 4 上加入,而在线成员将视图更改事件写入二进制日志。

图 20.9 成员加入

服务器 S4 加入组并寻找捐赠者。服务器 S1、S2 和 S3 分别为它们的二进制日志排队视图更改条目 VC4。与此同时,服务器 S1 正在接收新交易 T21。

状态转移:追赶

如果组成员和加入成员都使用克隆插件进行设置(参见第 20.5.4.2 节,“用于分布式恢复的克隆”),并且加入成员与组之间的事务差异超过了远程克隆操作的阈值(group_replication_clone_threshold),则 Group Replication 将开始使用远程克隆操作进行分布式恢复。如果所需事务不再存在于任何组成员的二进制日志文件中,则还会执行远程克隆操作。在远程克隆操作期间,加入成员上的现有数据将被删除,并替换为捐赠者的数据副本。当远程克隆操作完成并加入成员重新启动后,将从捐赠者的二进制日志进行状态转移,以获取在远程克隆操作进行时组应用的事务。如果没有大的事务间隙,或者未安装克隆插件,则 Group Replication 直接进行从捐赠者的二进制日志进行状态转移。

对于从捐赠者的二进制日志进行状态转移,加入成员与捐赠者之间建立连接并开始状态转移。这种与捐赠者的交互会一直持续,直到加入组的服务器的应用程序线程处理与加入组时触发的视图更改日志事件相对应的视图更改日志事件。换句话说,加入组的服务器会从捐赠者进行复制,直到到达与其当前所在的视图标记相匹配的视图标记为止。

图 20.10 状态转移:追赶上

服务器 S4 已选择服务器 S2 作为捐赠者。状态转移从服务器 S2 执行到服务器 S4,直至达到视图更改条目 VC4(view_id = VC4)。服务器 S4 使用临时应用程序缓冲区进行状态转移,其二进制日志目前为空。

由于视图标识符在同一逻辑时间传输到组中的所有成员,因此加入组的服务器知道应在哪个视图标识符处停止复制。这避免了复杂的 GTID 集计算,因为视图标识符清楚地标记了哪些数据属于每个组视图。

当加入组的服务器从捐赠者进行复制时,同时也会缓存来自组的传入事务。最终,它停止从捐赠者进行复制,并切换到应用那些已经缓存的事务。

图 20.11 排队事务

状态转移已完成。服务器 S4 已应用事务直至 T20 并将其写入二进制日志。服务器 S4 在恢复时,已将在视图更改后到达的事务 T21 缓存在临时应用程序缓冲区中。

完成:追赶上

当加入组的服务器识别到具有预期视图标识符的视图更改日志事件时,与提供者的连接将被终止,并开始应用缓存的事务。虽然它在二进制日志中充当标记,分隔视图更改,但视图更改日志事件还扮演另一个角色。它传达了所有服务器在加入组时感知到的认证信息,换句话说是最后一次视图更改。没有它,加入组的服务器将没有必要的信息来认证(检测冲突)后续事务。

追赶的持续时间不确定,因为它取决于工作负载和事务进入组的速率。这个过程完全在线进行,加入组的服务器在追赶时不会阻塞任何其他服务器。因此,当服务器进入这个阶段时落后的事务数量可能会因工作负载而变化,从而增加或减少。

当加入组的服务器达到零排队事务并且其存储的数据与其他成员相同时,其公共状态变为在线。

图 20.12 实例在线

服务器 S4 现在是组的在线成员。它已经应用了缓存事务 T21,因此其二进制日志显示与其他组成员的二进制日志相同,并且不再需要临时应用程序缓冲区。新的传入事务 T22 现在被所有组成员接收并应用。

20.5.5 支持 IPv6 和混合 IPv6 和 IPv4 组

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-ipv6.html

从 MySQL 8.0.14 开始,Group Replication 组成员可以使用 IPv6 地址作为组内通信的替代方案,而不是 IPv4 地址。要使用 IPv6 地址,服务器主机上的操作系统和 MySQL Server 实例都必须配置为支持 IPv6。有关为服务器实例设置 IPv6 支持的说明,请参见 Section 7.1.13, “IPv6 Support”。

IPv6 地址,或解析为其的主机名,可以被指定为成员在 group_replication_local_address 选项中提供给其他成员连接的网络地址。当与端口号一起指定时,IPv6 地址必须用方括号指定,例如:

group_replication_local_address= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"

group_replication_local_address 中指定的网络地址或主机名被 Group Replication 用作复制组内组成员的唯一标识符。如果为服务器实例指定的 Group Replication 本地地址的主机名解析为 IPv4 和 IPv6 地址,那么始终使用 IPv4 地址进行 Group Replication 连接。指定为 Group Replication 本地地址的地址或主机名与 MySQL 服务器 SQL 协议主机和端口不同,并且不在服务器实例的 bind_address 系统变量中指定。为了 Group Replication 的 IP 地址权限目的(参见 Section 20.6.4, “Group Replication IP Address Permissions”),您在 group_replication_local_address 中为每个组成员指定的地址必须添加到复制组中其他服务器的 group_replication_ip_allowlist(从 MySQL 8.0.22 开始)或 group_replication_ip_whitelist 系统变量的列表中。

复制组可以包含将 IPv6 地址作为其 Group Replication 本地地址的成员组合,以及呈现 IPv4 地址的成员。当服务器加入这样的混合组时,必须使用种子成员在 group_replication_group_seeds 选项中广告的协议进行初始联系,无论是 IPv4 还是 IPv6。如果组的任何种子成员在 group_replication_group_seeds 选项中列出了具有 IPv6 地址的情况,而加入成员具有 IPv4 Group Replication 本地地址,或者反之,则还必须为加入成员为所需协议设置和允许替代地址(或解析为该协议地址的主机名)。如果加入成员没有适当协议的允许地址,则其连接尝试将被拒绝。替代地址或主机名只需要添加到复制组中其他服务器的 group_replication_ip_allowlist(从 MySQL 8.0.22 开始)或 group_replication_ip_whitelist 系统变量中,而不需要添加到加入成员的 group_replication_local_address 值(该值只能包含单个地址)。

例如,服务器 A 是一个组的种子成员,并具有以下 Group Replication 的配置设置,以便在 group_replication_group_seeds 选项中广告 IPv6 地址:

group_replication_bootstrap_group=on
group_replication_local_address= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"
group_replication_group_seeds= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"

服务器 B 是组的加入成员,并具有以下 Group Replication 的配置设置,以便具有 IPv4 Group Replication 本地地址:

group_replication_bootstrap_group=off
group_replication_local_address= "203.0.113.21:33061"
group_replication_group_seeds= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"

服务器 B 还具有替代 IPv6 地址 2001:db8:8b0:40:3d9c:cc43:e006:19e8。为了成功加入组,服务器 B 的 IPv4 Group Replication 本地地址和其替代 IPv6 地址都必须列在服务器 A 的允许列表中,如下例所示:

group_replication_ip_allowlist=
"203.0.113.0/24,2001:db8:85a3:8d3:1319:8a2e:370:7348,
2001:db8:8b0:40:3d9c:cc43:e006:19e8"

作为 Group Replication IP 地址权限的最佳实践,服务器 B(以及所有其他组成员)应具有与服务器 A 相同的允许列表,除非安全要求另有规定。

如果复制组的任何成员或所有成员使用不支持在组复制中使用 IPv6 地址的较旧 MySQL Server 版本,则成员无法使用 IPv6 地址(或解析为 IPv6 地址的主机名)作为其组复制本地地址参与组。这适用于至少一个现有成员使用 IPv6 地址且不支持此功能的新成员尝试加入的情况,以及新成员尝试使用 IPv6 地址加入但组中至少有一个成员不支持此功能的情况。在每种情况下,新成员都无法加入。要使加入成员提供 IPv4 地址进行组通信,您可以将 group_replication_local_address 的值更改为 IPv4 地址,或配置您的 DNS 将加入成员的现有主机名解析为 IPv4 地址。在将每个组成员升级到支持 IPv6 用于组复制的 MySQL Server 版本后,您可以将每个成员的 group_replication_local_address 值更改为 IPv6 地址,或配置您的 DNS 提供 IPv6 地址。更改 group_replication_local_address 的值仅在停止并重新启动组复制时生效。

IPv6 地址还可以用作分布式恢复端点,从 MySQL 8.0.21 开始,可以使用 group_replication_advertise_recovery_endpoints 系统变量指定。在此列表中使用的地址适用相同的规则。请参阅 Section 20.5.4.1, “Connections for Distributed Recovery”。

20.5.6 使用 MySQL Enterprise Backup 与组复制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-enterprise-backup.html

MySQL Enterprise Backup 是 MySQL Server 的商业许可备份实用程序,可与MySQL Enterprise Edition一起使用。本节解释了如何使用 MySQL Enterprise Backup 备份并随后恢复组复制成员。相同的技术可以用于快速向组中添加新成员。

使用 MySQL Enterprise Backup 备份组复制成员

备份组复制成员类似于备份独立的 MySQL 实例。以下说明假定您已经熟悉如何使用 MySQL Enterprise Backup 执行备份;如果不是这种情况,请查看 MySQL Enterprise Backup 8.0 用户指南,特别是备份数据库服务器。还请注意授予 MySQL 特权给备份管理员和使用 MySQL Enterprise Backup 与组复制中描述的要求。

考虑以下具有三个成员s1s2s3的组,运行在具有相同名称的主机上:

mysql> SELECT member_host, member_port, member_state FROM performance_schema.replication_group_members;
+-------------+-------------+--------------+
| member_host | member_port | member_state |
+-------------+-------------+--------------+
| s1          |        3306 | ONLINE       |
| s2          |        3306 | ONLINE       |
| s3          |        3306 | ONLINE       |
+-------------+-------------+--------------+

使用 MySQL Enterprise Backup,在其主机上发出以下命令,例如,创建s2的备份:

s2> mysqlbackup --defaults-file=/etc/my.cnf --backup-image=/backups/my.mbi_`date +%d%m_%H%M` \
		      --backup-dir=/backups/backup_`date +%d%m_%H%M` --user=root -p \
--host=127.0.0.1 backup-to-image

注意

  • 对于 MySQL Enterprise Backup 8.0.18 及更早版本,如果系统变量sql_require_primary_key设置为ON,MySQL Enterprise Backup 无法在服务器上记录备份进度。这是因为服务器上的backup_progress表是一个 CSV 表,不支持主键。在这种情况下,mysqlbackup在备份操作期间会发出以下警告:

    181011 11:17:06 MAIN WARNING: MySQL query 'CREATE TABLE IF NOT EXISTS
    mysql.backup_progress( `backup_id` BIGINT NOT NULL, `tool_name` VARCHAR(4096)
    NOT NULL, `error_code` INT NOT NULL, `error_message` VARCHAR(4096) NOT NULL,
    `current_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP               ON
    UPDATE CURRENT_TIMESTAMP,`current_state` VARCHAR(200) NOT NULL ) ENGINE=CSV
    DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin': 3750, Unable to create a table
    without PK, when system variable 'sql_require_primary_key' is set. Add a PK
    to the table or unset this variable to avoid this message. Note that tables
    without PK can cause performance problems in row-based replication, so please
    consult your DBA before changing this setting.
    181011 11:17:06 MAIN WARNING: This backup operation's progress info cannot be
    logged.
    

    这并不会阻止mysqlbackup完成备份。

  • 对于 MySQL Enterprise Backup 8.0.20 及更早版本,当备份次要成员时,由于 MySQL Enterprise Backup 无法将备份状态和元数据写入只读服务器实例,可能会在备份操作期间发出类似以下警告:

    181113 21:31:08 MAIN WARNING: This backup operation cannot write to backup
    progress. The MySQL server is running with the --super-read-only option.
    

    您可以通过在备份命令中使用--no-history-logging选项来避免警告。对于 MySQL Enterprise Backup 8.0.21 及更高版本,这不是问题—请参阅使用 MySQL Enterprise Backup 与组复制获取详细信息。

恢复失败的成员

假设其中一个成员(以下示例���的s3)无法协调。可以使用组成员s2的最新备份来恢复s3。以下是执行恢复的步骤:

  1. 将 s2 的备份复制到 s3 的主机上。复制备份的确切方式取决于您可用的操作系统和工具。在本例中,我们假设主机都是 Linux 服务器,并使用 SCP 在它们之间复制文件:

    s2/backups> scp my.mbi_2206_1429 s3:/backups
    
  2. 恢复备份。连接到目标主机(在本例中为s3的主机),并使用 MySQL Enterprise Backup 恢复备份。以下是步骤:

    1. 停止受损服务器,如果它仍在运行。例如,在使用 systemd 的 Linux 发行版上:

      s3> systemctl stop mysqld
      
    2. 将受损服务器的数据目录中的两个配置文件auto.cnfmysqld-auto.cnf(如果存在)复制到数据目录之外的安全位置以保存服务器的 UUID 和 Section 7.1.9.3,“持久化系统变量”(如果使用),这些在下面的步骤中是必需的。

    3. 删除s3的数据目录中的所有内容。例如:

      s3> rm -rf /var/lib/mysql/*
      

      如果系统变量innodb_data_home_dirinnodb_log_group_home_dir,和innodb_undo_directory指向除数据目录之外的任何目录,则它们也应该被清空;否则,恢复操作将失败。

    4. s2的备份恢复到s3的主机上:

      s3> mysqlbackup --defaults-file=/etc/my.cnf \
        --datadir=/var/lib/mysql \
        --backup-image=/backups/my.mbi_2206_1429  \
      --backup-dir=/tmp/restore_`date +%d%m_%H%M` copy-back-and-apply-log
      

      注意

      上述命令假定s2s3上的二进制日志和中继日志具有相同的基本名称,并且位于两个服务器上的相同位置。如果不满足这些条件,您应该使用--log-bin--relay-log选项将二进制日志和中继日志恢复到s3上的原始文件路径。例如,如果您知道在s3上二进制日志的基本名称是s3-bin,中继日志的基本名称是s3-relay-bin,则您的恢复命令应如下所示:

      mysqlbackup --defaults-file=/etc/my.cnf \
        --datadir=/var/lib/mysql \
        --backup-image=/backups/my.mbi_2206_1429  \
        --log-bin=s3-bin --relay-log=s3-relay-bin \
        --backup-dir=/tmp/restore_`date +%d%m_%H%M` copy-back-and-apply-log
      

      能够将二进制日志和中继日志恢复到正确的文件路径会使恢复过程更容易;如果由于某种原因这是不可能的,请参阅重建失败的成员以作为新成员重新加入。

  3. 恢复 s3 的auto.cnf文件。为了重新加入复制组,恢复的成员必须具有加入组之前使用的相同的server_uuid。通过将在步骤 2 中保留的auto.cnf文件复制到恢复成员的数据目录中来提供旧的服务器 UUID。

    注意

    如果您无法通过恢复其旧的auto.cnf文件向恢复的成员提供失败成员的原始server_uuid,则必须让恢复的成员作为新成员加入组;请参见下面的重建失败的成员以重新加入作为新成员中的说明。

  4. s3恢复mysqld-auto.cnf文件(仅在s3使用持久系统变量时需要)。 必须提供用于配置失败成员的 Section 7.1.9.3,“持久系统变量”的设置,这些设置可以在失败服务器的mysqld-auto.cnf文件中找到,您应该在上述第 2 步中保留该文件。将文件恢复到恢复服务器的数据目录中。请参阅恢复持久系统变量以了解如果没有文件副本该怎么办。

  5. 启动恢复服务器。 例如,在使用 systemd 的 Linux 发行版上:

    systemctl start mysqld
    

    注意

    如果您正在恢复的服务器是主要成员,请在启动恢复服务器之前执行恢复主要成员中描述的步骤。

  6. 重新启动 Group Replication。 连接到重新启动的s3,例如,使用mysql客户端,并执行以下命令:

    mysql> START GROUP_REPLICATION;
    

    在恢复的实例可以成为组的在线成员之前,需要应用在备份之后发生的任何事务;这是通过使用 Group Replication 的分布式恢复机制实现的,该过程在发出 START GROUP_REPLICATION 语句后开始。要检查恢复实例的成员状态,请执行:

    mysql> SELECT member_host, member_port, member_state FROM performance_schema.replication_group_members;
    +-------------+-------------+--------------+
    | member_host | member_port | member_state |
    +-------------+-------------+--------------+
    | s1          |        3306 | ONLINE       |
    | s2          |        3306 | ONLINE       |
    | s3          |        3306 | RECOVERING   |
    +-------------+-------------+--------------+
    

    这表明s3正在应用事务以赶上组的进度。一旦它赶上了组的其他成员,它的member_state就会变为ONLINE

    mysql> SELECT member_host, member_port, member_state FROM performance_schema.replication_group_members;
    +-------------+-------------+--------------+
    | member_host | member_port | member_state |
    +-------------+-------------+--------------+
    | s1          |        3306 | ONLINE       |
    | s2          |        3306 | ONLINE       |
    | s3          |        3306 | ONLINE       |
    +-------------+-------------+--------------+
    

    注意

    如果您正在恢复的服务器是主要成员,一旦它与组同步并变为ONLINE,请执行恢复主要成员末尾描述的步骤,以恢复您在启动服务器之前所做的配置更改。

该成员现在已经完全从备份中恢复,并作为组的常规成员运行。

重建失败的成员以重新加入作为新成员

有时,恢复失败成员中概述的步骤无法执行,因为例如二进制日志或中继日志已损坏,或者在备份中丢失。在这种情况下,使用备份重建成员,然后将其作为新成员添加到组中。在以下步骤中,我们假设重建的成员命名为s3,与失败的成员相同,并且在与s3相同的主机上运行:

  1. s2的备份复制到s3的主机上。复制备份的确切方式取决于您所使用的操作系统和可用工具。在本示例中,我们假设主机都是 Linux 服务器,并使用 SCP 在它们之间复制文件:

    s2/backups> scp my.mbi_2206_1429 s3:/backups
    
  2. 恢复备份。连接到目标主机(在本例中为s3的主机),并使用 MySQL Enterprise Backup 恢复备份。以下是步骤:

    1. 停止受损的服务器,如果它仍在运行。例如,在使用 systemd 的 Linux 发行版上:

      s3> systemctl stop mysqld
      
    2. 保留配置文件mysqld-auto.cnf,如果在受损服务器的数据目录中找到,则将其复制到数据目录之外的安全位置。这是为了保留服务器的第 7.1.9.3 节,“持久化系统变量”,稍后会用到。

    3. 删除s3的数据目录中的所有内容。例如:

      s3> rm -rf /var/lib/mysql/*
      

      如果系统变量innodb_data_home_dirinnodb_log_group_home_dirinnodb_undo_directory指向除数据目录以外的任何目录,则这些目录也应该清空;否则,恢复操作将失败。

    4. s2的备份恢复到s3的主机上。通过这种方法,我们正在将s3重新构建为一个新成员,因此我们不需要或不想使用备份中的旧二进制日志和中继日志;因此,如果这些日志已包含在您的备份中,请使用--skip-binlog--skip-relaylog选项排除它们:

      s3> mysqlbackup --defaults-file=/etc/my.cnf \
        --datadir=/var/lib/mysql \
        --backup-image=/backups/my.mbi_2206_1429  \
        --backup-dir=/tmp/restore_`date +%d%m_%H%M` \
        --skip-binlog --skip-relaylog \
      copy-back-and-apply-log
      

      注意

      如果您在备份中有健康的二进制日志和中继日志,可以毫无问题地将其传输到目标主机上,建议您按照上述恢复失败成员中描述的更简单的过程进行操作。

  3. s3恢复mysqld-auto.cnf文件(仅在s3使用持久系统变量时需要)。 必须提供用于配置失败成员的 Section 7.1.9.3, “Persisted System Variables”的设置,这些设置可以在失败服务器的mysqld-auto.cnf文件中找到,您应该在上述第 2 步中保留该文件。将文件恢复到恢复服务器的数据目录中。如果您没有文件副本,则请参阅恢复持久系统变量。

    注意

    不要将损坏服务器的auto.cnf文件恢复到新成员的数据目录中——当重建的s3作为新成员加入组时,它将被分配一个新的服务器 UUID。

  4. 启动恢复的服务器。 例如,在使用 systemd 的 Linux 发行版上:

    systemctl start mysqld
    

    注意

    如果您正在恢复的服务器是主要成员,请在启动恢复的服务器之前执行恢复主要成员中描述的步骤。

  5. 重新配置恢复的成员以加入组复制。 使用mysql客户端连接到恢复的服务器,并使用以下命令重置源和副本信息:

    mysql> RESET MASTER;
    
    mysql> RESET SLAVE ALL;
    Or from MySQL 8.0.22:
    mysql> RESET REPLICA ALL;
    

    为了使恢复的服务器能够使用组复制的内置机制进行分布式恢复,配置服务器的gtid_executed变量。为此,请使用备份的s2中包含的backup_gtid_executed.sql文件,该文件通常在恢复成员的数据目录下恢复。禁用二进制日志记录,使用backup_gtid_executed.sql文件配置gtid_executed,然后通过您的mysql客户端发出以下语句重新启用二进制日志记录:

    mysql> SET SQL_LOG_BIN=OFF;
    mysql> SOURCE *datadir*/backup_gtid_executed.sql
    mysql> SET SQL_LOG_BIN=ON;
    

    然后,在成员上配置组复制用户凭据:

    mysql> CHANGE MASTER TO MASTER_USER='*rpl_user*', MASTER_PASSWORD='*password*' /
    		FOR CHANNEL 'group_replication_recovery';
    
    Or from MySQL 8.0.23:
    mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='*rpl_user*', SOURCE_PASSWORD='*password*' /
    		FOR CHANNEL 'group_replication_recovery';
    
  6. 重新启动组复制。 使用您的mysql客户端向恢复的服务器发出以下命令:

    mysql> START GROUP_REPLICATION;
    

    在恢复的实例可以成为组的在线成员之前,需要将备份后组中发生的任何事务应用到实例上;这是通过使用 Group Replication 的分布式恢复机制实现的,该过程在发出 START GROUP_REPLICATION 语句后开始。要检查恢复实例的成员状态,请执行:

    mysql> SELECT member_host, member_port, member_state FROM performance_schema.replication_group_members;
    +-------------+-------------+--------------+
    | member_host | member_port | member_state |
    +-------------+-------------+--------------+
    | s3          |        3306 | RECOVERING   |
    | s2          |        3306 | ONLINE       |
    | s1          |        3306 | ONLINE       |
    +-------------+-------------+--------------+
    

    这表明s3正在应用事务以赶上组的进度。一旦它赶上了组的其他成员,其member_state将变为ONLINE

    mysql> SELECT member_host, member_port, member_state FROM performance_schema.replication_group_members;
    +-------------+-------------+--------------+
    | member_host | member_port | member_state |
    +-------------+-------------+--------------+
    | s3          |        3306 | ONLINE       |
    | s2          |        3306 | ONLINE       |
    | s1          |        3306 | ONLINE       |
    +-------------+-------------+--------------+
    

    注意

    如果您正在恢复的服务器是主要成员,在它与组同步并变为ONLINE后,执行恢复主要成员末尾描述的步骤,以恢复在启动之前对服务器所做的配置更改。

该成员现在已经作为新成员恢复到组中。

恢复持久化系统变量。 mysqlbackup不支持备份或保留 Section 7.1.9.3, “Persisted System Variables” ——文件mysqld-auto.cnf不包含在备份中。要使用其持久化变量设置启动恢复的成员,您需要执行以下操作之一:

  • 保留从损坏服务器复制的mysqld-auto.cnf文件,并将其复制到恢复服务器的数据目录。

  • 从组的另一个成员复制mysqld-auto.cnf文件到恢复服务器的数据目录,如果该成员具有与损坏成员相同的持久化系统变量设置。

  • 在启动恢复服务器并重新启动 Group Replication 之前,通过mysql客户端手动将所有系统变量设置为其持久化值。

恢复主要成员。 如果恢复的成员是组中的主要成员,则在 Group Replication 分布式恢复过程中必须注意防止对恢复数据库的写入。根据客户端访问组的方式,存在在恢复成员在网络上可访问之前执行 DML 语句的可能性,而在成员完成赶上其离线期间错过的活动之前。为了避免这种情况,在启动恢复服务器之前,在服务器选项文件中配置以下系统变量:

group_replication_start_on_boot=OFF
super_read_only=ON
event_scheduler=OFF

这些设置确保成员在启动时变为只读,并且在成员在分布式恢复过程中与组进行同步期间关闭事件调度程序。客户端还必须配置足够的错误处理,因为在恢复的成员上在此期间暂时阻止执行 DML 操作。一旦恢复过程完全完成,并且恢复的成员与组的其余部分同步,撤销这些更改;重新启动事件调度程序:

mysql> SET global event_scheduler=ON;

编辑成员选项文件中的以下系统变量,以便为下一次启动正确配置事物:

group_replication_start_on_boot=ON
super_read_only=OFF
event_scheduler=ON

20.6 组复制安全性

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-security.html

20.6.1 用于连接安全管理的通信堆栈

20.6.2 使用安全套接字层(SSL)保护组通信连接

20.6.3 保护分布式恢复连接

20.6.4 组复制 IP 地址权限

本节解释了如何保护一个组,保护组成员之间的连接,或通过建立 IP 地址白名单来建立安全边界。

20.6.1 连接安全管理的通信堆栈

译文:dev.mysql.com/doc/refman/8.0/en/group-replication-connection-security.html

从 MySQL 8.0.27 开始,Group Replication 可以通过以下方法之一保护成员之间的组通信连接:

  • 使用其自身的安全协议实现,包括 TLS/SSL 和用于传入组通信系统(GCS)连接的白名单。这是 MySQL 8.0.26 及更早版本的唯一选项。

  • 使用 MySQL 服务器自身的连接安全代替 Group Replication 的实现。使用 MySQL 协议意味着可以使用标准的用户认证方法来授予(或撤销)对组的访问权限,而不是使用白名单,并且服务器协议的最新功能始终在发布时可用。此选项从 MySQL 8.0.27 开始提供。

通过设置系统变量group_replication_communication_stackXCOM来选择使用 Group Replication 的自身实现(这是默认选择),或者设置为MYSQL以使用 MySQL 服务器的连接安全。

复制组要使用 MySQL 通信堆栈,需要进行以下额外配置。当您从使用 XCom 通信堆栈切换到 MySQL 通信堆栈时,特别重要的是确保所有这些要求都得到满足。

MySQL 通信堆栈的 Group Replication 要求

  • group_replication_local_address系统变量配置的网络地址必须设置为 MySQL 服务器正在侦听的 IP 地址和端口之一,如服务器的bind_address系统变量所指定的那样。每个成员的 IP 地址和端口组合在组内必须是唯一的。建议为每个组成员配置group_replication_group_seeds系统变量,其中包含所有组成员的本地地址。

  • MySQL 通信栈支持网络命名空间,而 XCom 通信栈不支持。如果使用网络命名空间与组复制的本地地址(group_replication_local_address)一起使用,必须为每个组成员使用CHANGE REPLICATION SOURCE TO语句进行配置。此外,每个组成员的report_host服务器系统变量必须设置为报告命名空间。所有组成员必须使用相同的命名空间,以避免在分布式恢复期间可能出现的地址解析问题。

  • group_replication_ssl_mode系统变量必须设置为组通信所需的设置。此系统变量控制组通信是否启用或禁用 TLS/SSL。对于 MySQL 8.0.26 及更早版本,TLS/SSL 配置始终从服务器的 SSL 设置中获取;对于 MySQL 8.0.27 及更高版本,在使用 MySQL 通信栈时,TLS/SSL 配置将从组复制的分布式恢复设置中获取。为避免潜在冲突,此设置应在所有组成员上相同。

  • --ssl--skip-ssl服务器选项和require_secure_transport服务器系统变量的设置应在所有组成员上相同,以避免潜在冲突。如果group_replication_ssl_mode设置为REQUIREDVERIFY_CAVERIFY_IDENTITY,请使用--sslrequire_secure_transport=ON。如果group_replication_ssl_mode设置为DISABLED,请使用require_secure_transport=OFF

  • 如果为组通信启用了 TLS/SSL,则必须配置 Group Replication 的用于保护分布式恢复的设置,如果尚未配置,则必须配置,或者如果已经配置,则必须进行验证。MySQL 通信堆栈不仅在成员之间的分布式恢复连接中使用这些设置,还在一般组通信中使用 TLS/SSL 配置。group_replication_recovery_use_ssl和其他group_replication_recovery_*系统变量在第 20.6.3.2 节,“用于分布式恢复的安全套接字层(SSL)连接”中有解释。

  • 当组使用 MySQL 通信堆栈时,不使用 Group Replication 白名单,因此group_replication_ip_allowlistgroup_replication_ip_whitelist系统变量将被忽略,无需配置。

  • Group Replication 用于分布式恢复的复制用户帐户,如使用CHANGE REPLICATION SOURCE TO语句配置的,用于在设置 Group Replication 连接时由 MySQL 通信堆栈进行身份验证。这个用户帐户在所有组成员上都是相同的,必须具有以下权限:

    • GROUP_REPLICATION_STREAM。此权限是用户帐户能够使用 MySQL 通信堆栈建立 Group Replication 连接所必需的。

    • CONNECTION_ADMIN。此权限是为了确保 Group Replication 连接在涉及的服务器之一处于离线模式时不会被终止。如果使用 MySQL 通信堆栈而没有此权限,则被放置在离线模式的成员将被从组中驱逐。

    这些权限是所有复制用户帐户必须具有的权限REPLICATION SLAVEBACKUP_ADMIN的附加权限(请参阅第 20.2.1.3 节,“用于分布式恢复的用户凭据”)。在添加新权限时,请确保在发出GRANT语句之前通过发出SET SQL_LOG_BIN=0跳过每个组成员上的二进制日志记录,并在之后通过SET SQL_LOG_BIN=1,以便本地事务不会干扰 Group Replication 的重新启动。

group_replication_communication_stack实际上是一个群组范围的配置设置,所有群组成员必须设置相同的值。然而,Group Replication 自身并不检查群组范围配置设置的一致性。一个值与其他群组成员不同的成员无法与其他成员通信,因为通信协议不兼容,所以无法交换关于其配置设置的信息。

这意味着虽然在 Group Replication 运行时可以更改系统变量的值,并在重新启动群组成员上的 Group Replication 后生效,但成员仍然无法重新加入群组,直到所有成员的设置都已更改。因此,您必须在所有成员上停止 Group Replication 并更改系统变量的值,然后才能重新启动群组。因为所有成员都已停止,所以需要通过一个具有group_replication_bootstrap_group=ON的服务器进行完整重启群组(引导)。在值更改生效之前,您可以在停止的群组成员上进行其他必要的设置更改。

对于一个运行中的群组,按照以下步骤更改group_replication_communication_stack的值和其他必要的设置,以将一个群组从 XCom 通信栈迁移到 MySQL 通信栈,或者从 MySQL 通信栈迁移到 XCom 通信栈:

  1. 在每个群组成员上停止 Group Replication,使用STOP GROUP_REPLICATION语句。最后停止主要成员,以免触发新的主要选举并等待其完成。

  2. 在每个群组成员上,将系统变量group_replication_communication_stack设置为新的通信栈,MYSQLXCOM,具体取决于情况。您可以通过编辑 MySQL 服务器配置文件(在 Linux 和 Unix 系统上通常命名为my.cnf,在 Windows 系统上为my.ini),或使用SET语句来完成。例如:

    SET PERSIST group_replication_communication_stack="MYSQL";
    
  3. 如果您正在将复制组从 XCom 通信堆栈(默认)迁移到 MySQL 通信堆栈,请在每个组成员上配置或重新配置所需的系统变量为适当的设置,如上述清单中所述。例如,group_replication_local_address系统变量必须设置为 MySQL 服务器正在侦听的 IP 地址和端口之一。还要使用CHANGE REPLICATION SOURCE TO语句配置任何网络命名空间。

  4. 如果您正在将复制组从 XCom 通信堆栈(默认)迁移到 MySQL 通信堆栈,请在每个组成员上发出GRANT语句,以赋予复制用户帐户GROUP_REPLICATION_STREAMCONNECTION_ADMIN权限。您需要将组成员从应用 Group Replication 停止时应用的只读状态中取出。还要确保在发出GRANT语句之前在每个组成员上跳过二进制日志记录,通过在发出语句之前执行SET SQL_LOG_BIN=0,并在之后执行SET SQL_LOG_BIN=1,以确保本地事务不会干扰重新启动 Group Replication。例如:

    SET GLOBAL SUPER_READ_ONLY=OFF;
    SET SQL_LOG_BIN=0; 
    GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%';
    GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
    SET SQL_LOG_BIN=1;
    
  5. 如果您正在将复制组从 MySQL 通信堆栈迁移回 XCom 通信堆栈,请在每个组成员上重新配置上述要求中的系统变量,以适合 XCom 通信堆栈的设置。第 20.9 节,“组复制变量”列出了系统变量及其默认值以及 XCom 通信堆栈的要求。

    注意

    • XCom 通信堆栈不支持网络命名空间,因此组复制本地地址(group_replication_local_address系统变量)不能使用这些。通过发出CHANGE REPLICATION SOURCE TO语句取消设置。

    • 当切换回 XCom 通信堆栈时,由group_replication_recovery_use_ssl和其他group_replication_recovery_*系统变量指定的设置不用于保护组通信。相反,组复制系统变量group_replication_ssl_mode用于激活 SSL 用于组通信连接并指定连接的安全模式,其余配置取自服务器的 SSL 配置。有关详细信息,请参见第 20.6.2 节“使用安全套接字层(SSL)保护组通信连接”。

  6. 要重新启动组,请按照第 20.5.2 节“重新启动组”中的过程进行操作,该节解释了如何安全地引导已执行和认证事务的组。由具有group_replication_bootstrap_group=ON的服务器引导是必要的,以更改通信堆栈,因为所有成员必须关闭。

  7. 成员现在使用新的通信堆栈相互连接。任何将group_replication_communication_stack设置为先前通信堆栈(或在 XCom 的情况下默认设置)的服务器将无法加入该组。重要的是要注意,由于组复制甚至无法看到加入尝试,因此它不会检查并用错误消息拒绝加入成员。相反,当先前的通信堆栈放弃尝试联系新的通信堆栈时,尝试加入会悄无声息地失败。

20.6.2 用安全套接字层(SSL)保护组通信连接

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-secure-socket-layer-support-ssl.html

安全套接字可以用于组内成员之间的组通信连接。

Group Replication 系统变量group_replication_ssl_mode用于激活 SSL 用于组通信连接并指定连接的安全模式。默认设置意味着不使用 SSL。该选项有以下可能的值:

表 20.1 group_replication_ssl_mode 配置值

描述
DISABLED 建立一个未加密的连接(默认设置)。
REQUIRED 如果服务器支持安全连接,请建立安全连接。
VERIFY_CA 类似于REQUIRED,但另外根据配置的证书颁发机构(CA)证书验证服务器 TLS 证书。
VERIFY_IDENTITY 类似于VERIFY_CA,但另外验证服务器证书是否与尝试连接的主机匹配。

如果使用 SSL,则配置安全连接的方式取决于是使用 XCom 还是 MySQL 通信堆栈进行组通信(自 MySQL 8.0.27 起可选择两者之间的一个)。

当使用 XCom 通信堆栈(group_replication_communication_stack=XCOM)时: Group Replication 的组通信连接的其余配置取自服务器的 SSL 配置。有关配置服务器 SSL 的选项的更多信息,请参阅加密连接的命令选项。应用于 Group Replication 组通信连接的服务器 SSL 选项如下:

表 20.2 SSL 选项

服务器配置 描述
ssl_key SSL 私钥文件的路径名,格式为 PEM。在客户端端,这是客户端私钥。在服务器端,这是服务器私钥。
ssl_cert SSL 公钥证书文件的路径名,格式为 PEM。在客户端端,这是客户端公钥证书。在服务器端,这是服务器公钥证书。
ssl_ca 证书颁发机构(CA)证书文件的路径名,格式为 PEM。
ssl_capath 包含受信任的 SSL 证书颁发机构(CA)证书文件的目录路径名,格式为 PEM。
ssl_crl 包含证书吊销列表的 PEM 格式文件的路径名。
ssl_crlpath 包含 PEM 格式证书吊销列表文件的目录路径名。
ssl_cipher 用于加密连接的可接受密码列表。
tls_version 服务器允许用于加密连接的 TLS 协议列表。
tls_ciphersuites 服务器允许用于加密连接的 TLSv1.3 密码套件。

重要提示

  • 从 MySQL 8.0.28 版本开始,MySQL Server 移除了对 TLSv1 和 TLSv1.1 连接协议的支持。这些协议从 MySQL 8.0.26 开始被弃用,尽管 MySQL Server 客户端,包括作为客户端的 Group Replication 服务器实例,如果使用了弃用的 TLS 协议版本,不会向用户返回警告。有关更多信息,请参阅 移除对 TLSv1 和 TLSv1.1 协议的支持。

  • 从 MySQL 8.0.16 版本开始,MySQL Server 支持 TLSv1.3 协议,前提是 MySQL Server 使用 OpenSSL 1.1.1 进行编译。服务器在启动时检查 OpenSSL 的版本,如果低于 1.1.1,则将从与 TLS 版本相关的服务器系统变量的默认值中移除 TLSv1.3(包括 group_replication_recovery_tls_version 系统变量)。

  • MySQL 8.0.18 版本开始,Group Replication 支持 TLSv1.3。在 MySQL 8.0.16 和 MySQL 8.0.17 中,如果服务器支持 TLSv1.3,则协议不受组通信引擎支持,无法被 Group Replication 使用。

  • 在 MySQL 8.0.18 中,TLSv1.3 可用于 Group Replication 的分布式恢复连接,但 group_replication_recovery_tls_versiongroup_replication_recovery_tls_ciphersuites 系统变量不可用。因此,捐赠服务器必须允许至少一个默认启用的 TLSv1.3 密码套件的使用,如 第 8.3.2 节,“加密连接 TLS 协议和密码” 中所列。从 MySQL 8.0.19 开始,您可以使用选项配置客户端支持任何选择的密码套件,包括仅使用非默认密码套件。

  • tls_version系统变量中指定的 TLS 协议列表中,确保指定的版本是连续的(例如,TLSv1.2,TLSv1.3)。如果协议列表中存在任何间隙(例如,如果您指定了TLSv1,TLSv1.2,省略了 TLS 1.1),Group Replication 可能无法建立组通信连接。

在一个复制组中,OpenSSL 协商使用所有成员支持的最高 TLS 协议。一个配置为仅使用 TLSv1.3(tls_version=TLSv1.3)的加入成员无法加入一个不支持 TLSv1.3 的复制组,因为在这种情况下,组成员使用较低的 TLS 协议版本。为了将成员加入到组中,您必须配置加入成员也允许使用现有组成员支持的较低的 TLS 协议版本。相反,如果一个加入成员不支持 TLSv1.3,但现有组成员都支持并且在彼此之间的连接中使用该版本,那么如果现有组成员已经允许使用合适的较低 TLS 协议版本,或者您对其进行配置,该成员可以加入。在这种情况下,OpenSSL 使用较低的 TLS 协议版本进行每个成员到加入成员的连接。每个成员与其他现有成员的连接继续使用两个成员都支持的最高可用协议。

从 MySQL 8.0.16 开始,您可以在运行时更改 tls_version 系统变量以更改服务器的允许 TLS 协议版本列表。请注意,对于 Group Replication,ALTER INSTANCE RELOAD TLS 语句重新配置服务器的 TLS 上下文,从定义上下文的系统变量的当前值中获取,不会在运行 Group Replication 时更改 Group Replication 的组通信连接的 TLS 上下文。要将重新配置应用于这些连接,必须执行 STOP GROUP_REPLICATION,然后执行 START GROUP_REPLICATION 以重新启动已更改 tls_version 系统变量的成员或成员的 Group Replication。同样,如果要使组的所有成员更改为使用更高或更低的 TLS 协议版本,必须在更改允许的 TLS 协议版本列表后,在成员上执行滚动重启 Group Replication,以便 OpenSSL 在完成滚动重启时协商使用更高的 TLS 协议版本。有关在运行时更改允许的 TLS 协议版本列表的说明,请参见 第 8.3.2 节,“加密连接 TLS 协议和密码” 和 服务器端运行时配置和监视加密连接。

以下示例显示了配置服务器上 SSL 并激活 SSL 用于组复制组通信连接的 my.cnf 文件中的部分内容:

[mysqld]
ssl_ca = "cacert.pem"
ssl_capath = "/.../ca_directory"
ssl_cert = "server-cert.pem"
ssl_cipher = "DHE-RSA-AEs256-SHA"
ssl_crl = "crl-server-revoked.crl"
ssl_crlpath = "/.../crl_directory"
ssl_key = "server-key.pem"
group_replication_ssl_mode= REQUIRED

重要提示

ALTER INSTANCE RELOAD TLS 语句重新配置服务器的 TLS 上下文,从定义上下文的系统变量的当前值中获取,不会在运行 Group Replication 时更改 Group Replication 的组通信连接的 TLS 上下文。要将重新配置应用于这些连接,必须执行 STOP GROUP_REPLICATION,然后执行 START GROUP_REPLICATION 以重新启动 Group Replication。

加入成员和现有成员之间进行的分布式恢复连接不受上述选项的覆盖。这些连接使用 Group Replication 的专用分布式恢复 SSL 选项,详细描述在第 20.6.3.2 节,“用于分布式恢复的安全套接字层(SSL)连接”。

当使用 MySQL 通信堆栈(group_replication_communication_stack=MYSQL)时: 分布式恢复组的安全设置应用于组成员之间的正常通信。请参阅第 20.6.3 节,“保护分布式恢复连接”以了解如何配置安全设置。

20.6.3 保护分布式恢复连接

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-distributed-recovery-securing.html

20.6.3.1 为分布式恢复保护用户凭据

20.6.3.2 为分布式恢复配置安全套接字层 (SSL) 连接

重要提示

当使用 MySQL 通信栈(group_replication_communication_stack=MYSQL)并且成员之间的连接是安全的(group_replication_ssl_mode 未设置为 DISABLED)时,本节讨论的安全设置不仅适用于分布式恢复连接,还适用于一般组成员之间的组通信。

当成员加入组时,分布式恢复是通过远程克隆操作(如果可用且适用)和异步复制连接的组合来执行的。有关分布式恢复的详细描述,请参见 Section 20.5.4, “Distributed Recovery”。

在 MySQL 8.0.20 版本之前,组成员根据 MySQL 服务器的 hostnameport 系统变量,为加入成员提供标准的 SQL 客户端连接,用于分布式恢复。从 MySQL 8.0.21 开始,组成员可以为加入成员提供一组备用的分布式恢复端点,作为专用的客户端连接。更多详情请参见 Section 20.5.4.1, “Connections for Distributed Recovery”。请注意,为分布式恢复提供给加入成员的连接 并非 用于 Group Replication 在使用 XCom 通信栈进行组通信时在线成员之间通信的连接(group_replication_communication_stack=XCOM)。

为了保护组内的分布式恢复连接,请确保复制用户的用户凭据得到妥善保护,并在可能的情况下使用 SSL 进行分布式恢复连接。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-secure-user.html

20.6.3.1 为分布式恢复安全用户凭据

从二进制日志进行状态传输需要具有正确权限的复制用户,以便 Group Replication 可以建立直接成员之间的复制通道。相同的复制用户用于所有组成员的分布式恢复。如果组成员已设置为支持作为分布式恢复的一部分的远程克隆操作(从 MySQL 8.0.17 开始提供),则此复制用户也用作捐赠者上的克隆用户,并且对于此角色也需要正确的权限。有关设置此用户的详细说明,请参阅第 20.2.1.3 节,“分布式恢复的用户凭据”。

为了保护用户凭据,您可以要求用户帐户的连接使用 SSL,并且(从 MySQL 8.0.21 开始)可以在启动 Group Replication 时提供用户凭据,而不是将它们存储在副本状态表中。此外,如果您使用缓存 SHA-2 认证,您必须在组成员上设置 RSA 密钥对。

重要

当使用 MySQL 通信堆栈(group_replication_communication_stack=MYSQL)和成员之间的安全连接(group_replication_ssl_mode未设置为DISABLED)时,恢复用户必须正确设置,因为他们也是组通信的用户。请按照第 20.6.3.1.2 节,“具有 SSL 的复制用户”和第 20.6.3.1.3 节,“安全提供复制用户凭据”中的说明进行操作。

20.6.3.1.1 具有缓存 SHA-2 认证插件的复制用户

默认情况下,在 MySQL 8 中创建的用户使用第 8.4.1.2 节,“缓存 SHA-2 可插拔认证”。如果您为分布式恢复配置的复制用户使用缓存 SHA-2 认证插件,并且在分布式恢复连接中使用 SSL,那么 RSA 密钥对将用于密码交换。有关 RSA 密钥对的更多信息,请参阅第 8.3.3 节,“创建 SSL 和 RSA 证书和密钥”。

在这种情况下,您可以将rpl_user的公钥复制到加入成员,或者配置捐赠者在请求时提供公钥。更安全的方法是将复制用户帐户的公钥复制到加入成员。然后,您需要在加入成员上配置group_replication_recovery_public_key_path系统变量,指定复制用户帐户的公钥路径。

较不安全的方法是在捐赠者上设置group_replication_recovery_get_public_key=ON,以便它们向加入成员提供复制用户帐户的公钥。没有办法验证服务器的身份,因此只有在确定没有服务器身份被破坏的风险时才设置group_replication_recovery_get_public_key=ON,例如通过中间人攻击。

20.6.3.1.2 带 SSL 的复制用户

需要 SSL 连接的复制用户必须在服务器加入组(加入成员)连接到捐赠者之前创建。通常,在为服务器加入组进行配置时设置。要为需要 SSL 连接的分布式恢复创建一个复制用户,请在所有将参与组的服务器上发出以下语句:

mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER '*rec_ssl_user*'@'%' IDENTIFIED BY '*password*' REQUIRE SSL;
mysql> GRANT REPLICATION SLAVE ON *.* TO '*rec_ssl_user*'@'%';
mysql> GRANT CONNECTION_ADMIN ON *.* TO '*rec_ssl_user*'@'%';
mysql> GRANT BACKUP_ADMIN ON *.* TO '*rec_ssl_user*'@'%';
mysql> GRANT GROUP_REPLICATION_STREAM ON *.* TO *rec_ssl_user*@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;

注意

当使用 MySQL 通信堆栈(group_replication_communication_stack=MYSQL)和成员之间的安全连接(group_replication_ssl_mode未设置为DISABLED)时,需要GROUP_REPLICATION_STREAM权限。参见第 20.6.1 节,“连接安全管理的通信堆栈”。

20.6.3.1.3 安全提供复制用户凭据

要为复制用户提供用户凭据,您可以将它们永久设置为group_replication_recovery通道的凭据,使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句。另外,从 MySQL 8.0.21 开始,您可以在每次启动群组复制时在START GROUP_REPLICATION语句中指定它们。在START GROUP_REPLICATION上指定的用户凭据优先于使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句设置的任何用户凭据。

使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO设置的用户凭据以明文形式存储在服务器上的复制元数据存储库中,但在START GROUP_REPLICATION中指定的用户凭据仅保存在内存中,并且通过STOP GROUP_REPLICATION语句或服务器关闭时会被删除。因此,使用START GROUP_REPLICATION指定用户凭据有助于保护群组复制服务器免受未经授权的访问。然而,这种方法与通过group_replication_start_on_boot系统变量指定自动启动群组复制不兼容。

如果要永久设置用户凭据,请在准备加入群组的成员上发出CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO语句:

mysql> CHANGE MASTER TO MASTER_USER='*rec_ssl_user*', MASTER_PASSWORD='*password*' 
            FOR CHANNEL 'group_replication_recovery';

Or from MySQL 8.0.23:
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='*rec_ssl_user*', SOURCE_PASSWORD='*password*' 
            FOR CHANNEL 'group_replication_recovery';

在首次启动群组复制或服务器重新启动时,要在START GROUP_REPLICATION上提供用户凭据,请发出以下语句:

mysql> START GROUP_REPLICATION USER='*rec_ssl_user*', PASSWORD='*password*';

重要提示

如果您切换到使用START GROUP_REPLICATION在以前使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO提供凭据的服务器上指定用户凭据,您必须完成以下步骤以获得此更改的安全性好处。

  1. 使用STOP GROUP_REPLICATION语句在组成员上停止组复制。虽然在组复制运行时可以执行以下两个步骤,但需要重新启动组复制以实施更改。

  2. group_replication_start_on_boot系统变量的值设置为OFF(默认为ON)。

  3. 通过发出以下语句从副本状态表中删除分布式恢复凭据:

    mysql> CHANGE MASTER TO MASTER_USER='', MASTER_PASSWORD='' 
                FOR CHANNEL 'group_replication_recovery';
    
    Or from MySQL 8.0.23:
    mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='', SOURCE_PASSWORD='' 
                FOR CHANNEL 'group_replication_recovery';
    
  4. 使用指定分布式恢复用户凭据的START GROUP_REPLICATION语句在组成员上重新启动组复制。

如果不执行这些步骤,凭据将继续存储在副本状态表中,并且在远程克隆操作期间也可以传输到其他组成员,用于分布式恢复。然后,group_replication_recovery通道可能会意外地使用存储的凭据在原始成员或从原始成员克隆的成员上启动组复制。服务器启动时(包括远程克隆操作后)自动启动组复制将使用存储的用户凭据,如果操作员未在START GROUP_REPLICATION中指定分布式恢复凭据,则也会使用这些凭据。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-ssl-for-recovery.html

20.6.3.2 分布式恢复的安全套接字层(SSL)连接

重要

当使用 MySQL 通信堆栈(group_replication_communication_stack=MYSQL)和成员之间的安全连接(group_replication_ssl_mode 未设置为 DISABLED)时,本节讨论的安全设置不仅适用于分布式恢复连接,还适用于成员之间的组通信。请参阅 Section 20.6.1, “Communication Stack for Connection Security Management”。

无论是使用标准的 SQL 客户端连接还是分布式恢复端点进行分布式恢复连接,为了安全配置连接,您可以使用 Group Replication 的专用分布式恢复 SSL 选项。这些选项对应用于组通信连接的服务器 SSL 选项,但仅适用于分布式恢复连接。默认情况下,分布式恢复连接不使用 SSL,即使您为组通信连接激活了 SSL,服务器 SSL 选项也不适用于分布式恢复连接。您必须单独配置这些连接。

如果远程克隆操作作为分布式恢复的一部分使用,则 Group Replication 会自动配置克隆插件的 SSL 选项,以匹配您对分布式恢复 SSL 选项的设置。(有关克隆插件如何使用 SSL 的详细信息,请参阅 为克隆配置加密连接。)

分布式恢复 SSL 选项如下:

  • group_replication_recovery_use_ssl:设置为 ON 以使 Group Replication 在分布式恢复连接中使用 SSL,包括远程克隆操作和从捐赠者的二进制日志进行状态传输。您可以只设置此选项,而不设置其他分布式恢复 SSL 选项,在这种情况下,服务器会自动生成用于连接的证书,并使用默认的密码套件。如果要为连接配置证书和密码套件,请使用其他分布式恢复 SSL 选项进行配置。

  • group_replication_recovery_ssl_ca: 用于分布式恢复连接的证书颁发机构(CA)文件的路径名。Group Replication 会自动配置克隆 SSL 选项clone_ssl_ca以匹配此路径。

    group_replication_recovery_ssl_capath: 包含受信任 SSL 证书颁发机构(CA)证书文件的目录的路径名。

  • group_replication_recovery_ssl_cert: SSL 公钥证书文件的路径名,用于分布式恢复连接。Group Replication 会自动配置克隆 SSL 选项clone_ssl_cert以匹配此路径。

  • group_replication_recovery_ssl_key: SSL 私钥文件的路径名,用于分布式恢复连接。Group Replication 会自动配置克隆 SSL 选项clone_ssl_cert以匹配此路径。

  • group_replication_recovery_ssl_verify_server_cert: 使分布式恢复连接检查捐赠者发送证书中服务器的通用名称值。将此选项设置为ON相当于为群组通信连接的group_replication_ssl_mode选项设置VERIFY_IDENTITY

  • group_replication_recovery_ssl_crl: 包含证书吊销列表的文件的路径名。

  • group_replication_recovery_ssl_crlpath: 包含证书吊销列表的目录的路径名。

  • group_replication_recovery_ssl_cipher: 用于分布式恢复连接的连接加密的可接受密码列表。指定一个或多个以冒号分隔的密码名称列表。有关 MySQL 支持的加密密码的信息,请参见第 8.3.2 节,“加密连接 TLS 协议和密码”。

  • group_replication_recovery_tls_version: 一个逗号分隔的列表,包含了在这个服务器实例作为分布式恢复连接的客户端(即加入成员)时,连接加密所允许的一个或多个 TLS 协议。此系统变量的默认值取决于 MySQL Server 版本中支持的 TLS 协议版本。每个作为客户端(加入成员)和服务器(捐赠者)参与每个分布式恢复连接的组成员协商他们都设置支持的最高协议版本。此系统变量从 MySQL 8.0.19 版本开始提供。

  • group_replication_recovery_tls_ciphersuites: 一个以冒号分隔的列表,包含了在使用 TLSv1.3 进行连接加密时,分布式恢复连接的客户端(即加入成员)时所允许的一个或多个密码套件。如果在使用 TLSv1.3 时将此系统变量设置为NULL(如果您没有设置系统变量,则默认为此),则允许默认启用的密码套件,如第 8.3.2 节“加密连接 TLS 协议和密码”中所列出的。如果将此系统变量设置为空字符串,则不允许使用任何密码套件,因此也不会使用 TLSv1.3。此系统变量从 MySQL 8.0.19 版本开始提供。

20.6.4 组复制 IP 地址权限

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-ip-address-permissions.html

仅当使用 XCom 通信堆栈建立组通信时(group_replication_communication_stack=XCOM),组复制插件允许您指定一个主机允许列表,从中可以接受传入的组通信系统连接。如果在服务器 s1 上指定了一个允许列表,那么当服务器 s2 正在与 s1 建立连接以进行组通信时,s1 在接受来自 s2 的连接之前首先检查允许列表。如果 s2 在允许列表中,则 s1 接受连接,否则 s1 拒绝 s2 的连接尝试。从 MySQL 8.0.22 开始,系统变量group_replication_ip_allowlist用于指定允许列表,而对于 MySQL 8.0.22 之前的版本,使用系统变量group_replication_ip_whitelist。新的系统变量的工作方式与旧的系统变量相同,只是术语已更改。

注意

当使用 MySQL 通信堆栈建立组通信时(group_replication_communication_stack=MYSQL),group_replication_ip_allowlistgroup_replication_ip_whitelist的设置将被忽略。请参阅第 20.6.1 节,“连接安全管理的通信堆栈”。

如果您没有明确指定允许列表,则组通信引擎(XCom)会自动扫描主机上的活动接口,并识别具有私有子网地址的接口,以及为每个接口配置的子网掩码。这些地址以及 IPv4 的localhost IP 地址和(从 MySQL 8.0.14 开始)IPv6 用于创建自动组复制允许列表。因此,自动允许列表包括在适当的子网掩码应用后在主机中找到的以下范围的任何 IP 地址:

IPv4 (as defined in RFC 1918)
10/8 prefix       (10.0.0.0 - 10.255.255.255) - Class A
172.16/12 prefix  (172.16.0.0 - 172.31.255.255) - Class B
192.168/16 prefix (192.168.0.0 - 192.168.255.255) - Class C

IPv6 (as defined in RFC 4193 and RFC 5156)
fc00:/7 prefix    - unique-local addresses
fe80::/10 prefix  - link-local unicast addresses

127.0.0.1 - localhost for IPv4
::1       - localhost for IPv6

在错误日志中添加了一个条目,指出已自动允许主机的地址。

自动允许私有地址的白名单不能用于来自私有网络之外的服务器的连接,因此,即使服务器具有公共 IP 接口,也不会默认允许外部主机从外部连接到 Group Replication。对于位于不同机器上的服务器实例之间的 Group Replication 连接,您必须提供公共 IP 地址并将其指定为显式白名单。如果您为白名单指定任何条目,则私有和localhost地址不会自动添加,因此,如果您使用其中任何一个,必须明确指定。

要手动指定白名单,请使用group_replication_ip_allowlist(MySQL 8.0.22 及更高版本)或group_replication_ip_whitelist系统变量。在 MySQL 8.0.24 之前,您不能在服务器作为复制组的活动成员时更改白名单。如果成员处于活动状态,则必须在更改白名单之前执行STOP GROUP_REPLICATION,然后执行更改白名单,并在之后执行START GROUP_REPLICATION。从 MySQL 8.0.24 开始,您可以在 Group Replication 运行时更改白名单。

白名单必须包含在每个成员的group_replication_local_address系统变量中指定的 IP 地址或主机名。此地址与 MySQL 服务器 SQL 协议主机和端口不同,并且不在服务器实例的bind_address系统变量中指定。如果用作服务器实例的 Group Replication 本地地址的主机名解析为 IPv4 和 IPv6 地址,则 IPv4 地址优先用于 Group Replication 连接。

指定为分布式恢复端点的 IP 地址以及如果用于分布式恢复(这是默认设置)的成员标准 SQL 客户端连接的 IP 地址不需要添加到白名单中。白名单仅用于每个成员的group_replication_local_address指定的地址。加入成员必须通过白名单允许其对组的初始连接,以便检索用于分布式恢复的地址或地址。

在白名单中,您可以指定以下任意组合:

  • IPv4 地址(例如,198.51.100.44

  • 具有 CIDR 表示法的 IPv4 地址(例如,192.0.2.21/24

  • IPv6 地址,从 MySQL 8.0.14 开始(例如,2001:db8:85a3:8d3:1319:8a2e:370:7348

  • 具有 CIDR 表示法的 IPv6 地址,从 MySQL 8.0.14 开始(例如,2001:db8:85a3:8d3::/64

  • 主机名(例如,example.org

  • 使用 CIDR 表示法的主机名(例如,www.example.com/24

在 MySQL 8.0.14 之前,主机名只能解析为 IPv4 地址。从 MySQL 8.0.14 开始,主机名可以解析为 IPv4 地址、IPv6 地址或两者都可以。如果一个主机名同时解析为 IPv4 和 IPv6 地址,则始终使用 IPv4 地址进行组复制连接。您可以结合主机名或 IP 地址使用 CIDR 表示法来允许具有特定网络前缀的 IP 地址块,但请确保指定子网中的所有 IP 地址都在您的控制范围内。

注意

当因为 IP 地址不在允许列表中而拒绝连接尝试时,拒绝消息总是以 IPv6 格式打印 IP 地址。在此格式中,IPv4 地址以::ffff:开头(一个 IPv4 映射的 IPv6 地址)。您不需要使用此格式来指定允许列表中的 IPv4 地址;对于 IPv4 地址,请使用标准 IPv4 格式。

在允许列表中,每个条目之间必须用逗号分隔。例如:

mysql> SET GLOBAL group_replication_ip_allowlist="192.0.2.21/24,198.51.100.44,203.0.113.0/24,2001:db8:85a3:8d3:1319:8a2e:370:7348,example.org,www.example.com/24";

要加入复制组,服务器需要在其请求加入组的种子成员上获得许可。通常,这将是复制组的引导成员,但可以是任何在服务器配置中由group_replication_group_seeds选项列出的服务器之一。如果组的任何种子成员在加入成员具有 IPv4 group_replication_local_address时使用 IPv6 地址列出,或反之亦然,则还必须为加入成员为种子成员提供的协议设置和允许备用地址(或解析为该协议地址的主机名)。这是因为当服务器加入复制组时,必须使用种子成员在group_replication_group_seeds选项中广告的协议进行初始联系,无论是 IPv4 还是 IPv6。如果加入成员没有适当协议的允许地址,其连接尝试将被拒绝。有关管理混合 IPv4 和 IPv6 复制组的更多信息,请参见第 20.5.5 节,“IPv6 和混合 IPv6 和 IPv4 组的支持”。

当重新配置复制组(例如,选举新的主服务器或成员加入或离开时),组成员之间重新建立连接。如果一个组成员只被不再是复制组一部分的服务器允许访问,那么在重新配置后,它将无法重新连接到不允许它的剩余服务器。为了完全避免这种情况,请为所有作为复制组成员的服务器指定相同的白名单。

注意

根据您的安全要求,可以为不同的组成员配置不同的白名单,例如,为了保持不同的子网分开。如果您需要配置不同的白名单以满足安全要求,请确保在复制组中的白名单之间有足够的重叠,以最大限度地增加服务器在没有原始种子成员的情况下重新连接的可能性。

对于主机名,名称解析仅在另一个服务器发出连接请求时进行。无法解析的主机名不会被考虑用于白名单验证,并且会将警告消息写入错误日志。对已解析的主机名执行前向确认反向 DNS(FCrDNS)验证。

警告

主机名在白名单中比 IP 地址不安全。FCrDNS 验证提供了很好的保护水平,但可能会受到某些类型攻击的影响。仅在绝对必要时在白名单中指定主机名,并确保所有用于名称解析的组件,如 DNS 服务器,都在您的控制之下。您还可以使用 hosts 文件在本地实现名称解析,以避免使用外部组件。

20.7 群组复制性能和故障排除

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-performance.html

20.7.1 调整群组通信线程

20.7.2 流量控制

20.7.3 单一共识领导者

20.7.4 消息压缩

20.7.5 消息分段

20.7.6 XCom 缓存管理

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

20.7.8 处理网络分区和法定人数丢失

20.7.9 使用性能模式内存工具监控群组复制内存使用情况

群组复制旨在创建具有内置故障检测和自动恢复功能的容错系统。如果成员服务器实例自愿离开或停止与群组通信,剩余成员将在彼此之间达成群组重新配置的协议,并在需要时选择新的主服务器。被驱逐的成员会自动尝试重新加入群组,并通过分布式恢复使其保持最新。如果一个群组遇到困难,以至于无法与大多数成员联系以达成决策,它会标识自己已失去法定人数并停止处理事务。群组复制还具有内置机制和设置,帮助群组适应和管理工作负载和消息大小的变化,并保持在底层系统和网络资源的限制范围内。

群组复制的系统变量默认设置旨在最大化群组的性能和自主性。本节中的信息旨在帮助您配置一个复制群组,以优化自动处理您在特定系统上遇到的任何经常性问题,例如瞬时网络中断或超出服务器实例资源的工作负载和事务。

如果发现群组成员被频繁驱逐并重新加入群组,可能是因为群组复制的默认故障检测设置对您的系统过于敏感。这可能发生在较慢的网络或机器上,网络出现高频率的意外瞬时中断,或计划中的网络中断期间。有关通过调整设置处理该情况的建议,请参阅第 20.7.7 节“对故障检测和网络分区的响应”。

只有在 Group Replication 设置中发生组无法自动处理的情况时,您才需要手动干预。一些可能需要管理员干预的关键问题是当成员处于ERROR状态且无法重新加入组时,或者当网络分区导致组失去法定人数时。

  • 如果一个本来正常运行和配置的成员无法使用分布式恢复加入或重新加入组,并且保持在ERROR状态,Section 20.5.4.4, “Fault Tolerance for Distributed Recovery”,解释了可能出现的问题。一个可能的原因是加入成员有额外的事务,这些事务在组的现有成员中不存在。有关处理这种情况的建议,请参阅 Section 20.4.1, “GTIDs and Group Replication”。

  • 如果一个组失去了法定人数,这可能是由于网络分区将组分成两部分,或者可能是由于大多数服务器的故障。有关处理这种情况的建议,请参阅 Section 20.7.8, “Handling a Network Partition and Loss of Quorum”。

20.7.1 优化组通信线程

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-fine-tuning-the-group-communication-thread.html

当 Group Replication 插件加载时,组通信线程(GCT)在循环中运行。GCT 从组和插件接收消息,处理关于法定人数和故障检测的任务,发送一些保持活动的消息,并处理来自/发送到服务器/组的传入和传出事务。GCT 在队列中等待传入消息。当没有消息时,GCT 会等待。在实际进入睡眠之前,通过将这种等待时间设置得稍长一些(进行主动等待)可能在某些情况下证明是有益的。这是因为另一种选择是操作系统将 GCT 从处理器中切换出来并进行上下文切换。

要强制 GCT 进行主动等待,使用 group_replication_poll_spin_loops 选项,使 GCT 在实际轮询队列获取下一条消息之前,循环执行无关紧要的操作,达到配置的循环次数。

例如:

mysql> SET GLOBAL group_replication_poll_spin_loops= 10000;

20.7.2 流量控制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-flow-control.html

20.7.2.1 探针和统计信息

20.7.2.2 Group Replication 限流

Group Replication 确保事务仅在组中的大多数成员接收并就同时发送的所有事务之间的相对顺序达成一致后才提交。如果组中的总写入次数超过任何成员的写入容量,则此方法效果良好。如果确实如此,并且一些成员的写入吞吐量低于其他成员,特别是低于写入成员,则这些成员可能会开始落后于写入者。

使一些成员落后于组带来一些问题后果,特别是,这些成员上的读取可能会显示非常旧的数据。根据成员落后的原因,组中的其他成员可能需要保存更多或更少的复制上下文,以便能够满足来自慢速成员的潜在数据传输请求。

然而,在复制协议中有一种机制可以避免快速成员和慢速成员之间在应用的事务方面有太大的距离。这被称为流量控制机制。它试图解决几个目标:

  1. 保持成员之间足够接近,使缓冲和成员之间的去同步问题变得不那么严重;

  2. 快速适应不同工作负载或组中更多写入者等不同条件;

  3. 给每个成员公平分享可用写入容量;

  4. 不要将吞吐量降低到绝对必要的程度以避免浪费资源。

考虑到 Group Replication 的设计,是否进行限流取决于两个工作队列:(i) 认证 队列;(ii) 以及二进制日志 应用程序 队列。每当其中一个队列的大小超过用户定义的阈值时,限流机制就会被触发。只需配置:(i) 在认证者或应用程序级别进行流量控制,或两者都进行;以及 (ii) 每个队列的阈值是多少。

流量控制取决于两种基本机制:

  1. 监控成员以收集有关所有组成员的吞吐量和队列大小的一些统计信息,以便对每个成员应受到的最大写入压力进行合理猜测;

  2. 对于试图在每个时间点写入超出其公平份额的成员进行限流。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-probes-and-statistics.html

20.7.2.1 探针和统计信息

监控机制通过每个成员部署一组探针来收集有关其工作队列和吞吐量的信息来运作。然后定期将该信息传播给组,以与其他成员共享数据。

这些探针分散在插件堆栈中,允许建立诸如以下指标:

  • 认证者队列大小;

  • 复制应用程序队列大小;

  • 已认证的事务总数;

  • 在成员中应用的远程事务总数;

  • 本地事务总数。

一旦成员收到来自另一成员的带有统计信息的消息,它会计算关于上一个监控周期内认证、应用和本地执行的事务数量的其他指标。

监控数据定期与组内其他成员共享。监控周期必须足够长,以便其他成员决定当前的写入请求,但又足够短,以便对组带宽影响最小。信息每秒共享一次,这个周期足以解决这两个问题。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-throttling.html

20.7.2.2 组复制限流

基于在组中所有服务器收集的指标,限流机制会启动并决定是否限制成员能够执行/提交新事务的速率。

因此,从所有成员获取的指标是计算每个成员容量的基础:如果成员有一个大队列(用于认证或应用程序线程),那么执行新事务的能力应该接近上个周期认证或应用的事务。

组中所有成员的最低容量确定了组的实际容量,而本地事务的数量确定了有多少成员正在向其写入,因此,可用容量应该与多少成员共享。

这意味着每个成员都有一个根据可用容量确定的已建立的写入配额,换句话说,它可以安全地为下一个周期发出的事务数量。如果认证者或二进制日志应用程序的队列大小超过用户定义的阈值,写入配额将由限流机制执行。

配额将减少上个周期延迟的事务数量,然后再减少 10%,以允许触发问题的队列减小其大小。为了避免一旦队列大小超过阈值就出现大幅增加的吞吐量,吞吐量在此后每个周期只允许增长相同的 10%。

当前的限流机制不会对低于配额的事务进行惩罚,但会延迟完成那些超出配额的事务,直到监控周期结束。因此,如果写请求的配额非常小,一些事务的延迟可能接近监控周期。

20.7.3 单一共识领导者

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-single-consensus-leader.html

默认情况下,Group Replication 的组通信引擎(XCom,一种 Paxos 变体)使用复制组的每个成员作为领导者。从 MySQL 8.0.27 开始,当组处于单主模式时,组通信引擎可以使用单个领导者来驱动共识。在单主模式下使用单一共识领导者可以提高性能和韧性,特别是当组的某些次要成员当前无法访问时。

要使用单一共识领导者,组必须按以下方式配置:

  • 组必须处于单主模式。

  • group_replication_paxos_single_leader 系统变量必须设置为 ON。默认设置为 OFF 时,该行为被禁用。您必须对复制组进行完全重启(引导)以使 Group Replication 生效对此设置的更改。

  • Group Replication 通信协议版本必须设置为 8.0.27 或更高。使用 group_replication_get_communication_protocol() 函数查看组的通信协议版本。如果使用较低版本,则组无法使用此行为。如果所有组成员都支持,您可以使用 group_replication_set_communication_protocol() 函数将组的通信协议设置为更高版本。MySQL InnoDB Cluster 会自动管理通信协议版本。有关更多信息,请参见 Section 20.5.1.4, “Setting a Group's Communication Protocol Version”。

当配置完成后,Group Replication 指示组通信引擎使用组的主节点作为单一领导者来驱动共识。当选举出新的主节点时,Group Replication 会告知组通信引擎使用新的主节点。如果主节点当前不健康,组通信引擎会使用其他成员作为共识领导者。性能模式表 replication_group_communication_information 显示当前首选和实际共识领导者,首选领导者是 Group Replication 的选择,实际领导者是组通信引擎选择的领导者。

如果组处于多主模式,具有较低的通信协议版本,或者行为被group_replication_paxos_single_leader设置禁用,则所有成员都被用作领导者来推动共识。在这种情况下,性能模式表replication_group_communication_information显示所有成员都是首选和实际领导者。

在性能模式表replication_group_communication_information中的字段WRITE_CONSENSUS_SINGLE_LEADER_CAPABLE显示组是否支持使用单个领导者,即使在查询的成员上当前设置为OFFgroup_replication_paxos_single_leader。如果组是在启动时使用group_replication_paxos_single_leader设置为ON,并且其通信协议版本为 MySQL 8.0.27 或更高版本,则该字段设置为 1。此信息仅对处于ONLINERECOVERING状态的组成员返回。

20.7.4 消息压缩

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-message-compression.html

对于在线群组成员之间发送的消息,Group Replication 默认启用消息压缩。特定消息是否被压缩取决于您使用group_replication_compression_threshold系统变量配置的阈值。超过指定字节数的有效载荷的消息将被压缩。

默认压缩阈值为 1000000 字节。您可以使用以下语句将压缩阈值增加到 2MB,例如:

STOP GROUP_REPLICATION;
SET GLOBAL group_replication_compression_threshold = 2097152;
START GROUP_REPLICATION;

如果将group_replication_compression_threshold设置为零,则消息压缩将被禁用。

Group Replication 使用 LZ4 压缩算法来压缩组内发送的消息。请注意,LZ4 压缩算法支持的最大输入大小为 2113929216 字节。这个限制低于group_replication_compression_threshold系统变量的最大可能值,该值与 XCom 接受的最大消息大小相匹配。因此,LZ4 最大输入大小是消息压缩的实际限制,当启用消息压缩时,超过此大小的事务无法提交。使用 LZ4 压缩算法时,请不要为group_replication_compression_threshold设置大于 2113929216 字节的值。

Group Replication 不要求所有组成员的group_replication_compression_threshold的值相同。然而,建议在所有组成员上设置相同的值,以避免事务不必要的回滚、消息传递失败或消息恢复失败。

从 MySQL 8.0.18 开始,您还可以为通过从捐赠者的二进制日志进行状态传输的分布式恢复发送的消息配置压缩。这些消息的压缩,从已在组中的捐赠者发送到加入成员,是通过group_replication_recovery_compression_algorithmsgroup_replication_recovery_zstd_compression_level系统变量分别控制。有关更多信息,请参见 Section 6.2.8,“连接压缩控制”。

二进制日志事务压缩(自 MySQL 8.0.20 起可用),由binlog_transaction_compression系统变量激活,也可用于节省带宽。当事务负载在组成员之间传输时保持压缩。如果您将二进制日志事务压缩与 Group Replication 的消息压缩结合使用,消息压缩的作用机会较少,但仍可压缩标头以及未压缩的事件和事务负载。有关二进制日志事务压缩的更多信息,请参见 Section 7.4.4.5,“二进制日志事务压缩”。

组内发送的消息的压缩发生在组通信引擎级别,即在数据交给组通信线程之前,因此在mysql用户会话线程的上下文中进行。如果消息负载大小超过group_replication_compression_threshold设置的阈值,事务负载在发送到组之前会被压缩,并在接收时解压缩。接收消息时,成员会检查消息信封以验证是否已压缩。如果需要,则成员在将事务传递到上层之前对其进行解压缩。此过程如下图所示。

图 20.13 压缩支持

MySQL Group Replication 插件架构如前文所述,插件的五个层位于 MySQL 服务器和复制组之间。压缩和解压缩由 Group Communication System API 处理,这是 Group Replication 插件的第四层。组通信引擎(插件的第五层)和组成员使用数据量较小的压缩事务。MySQL 服务器核心和 Group Replication 插件的三个更高层(API、捕获、应用和恢复组件以及复制协议模块)使用数据量较大的原始事务。

当网络带宽成为瓶颈时,消息压缩可以在组通信级别提供高达 30-40%的吞吐量改进。这在负载下的大型服务器组的情况下尤为重要。组内N个参与者之间的互连是 TCP 点对点的性质,使发送方将相同数量的数据发送N次。此外,二进制日志可能具有较高的压缩比。这使得压缩成为包含大型事务的 Group Replication 工作负载的一个引人注目的特性。

20.7.5 消息分段

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-performance-message-fragmentation.html

当在 Group Replication 组成员之间发送异常大的消息时,可能导致一些组成员被报告为失败并从组中驱逐。这是因为 Group Replication 的组通信引擎(XCom,一种 Paxos 变体)使用的单个线程在处理消息时占用时间过长,因此一些组成员可能会将接收者报告为失败。从 MySQL 8.0.16 开始,默认情况下,大消息会自动分割成单独发送并由接收方重新组装的片段。

系统变量group_replication_communication_max_message_size指定了 Group Replication 通信的最大消息大小,超过该大小的消息将被分段。默认的最大消息大小为 10485760 字节(10 MiB)。允许的最大值与replica_max_allowed_packetslave_max_allowed_packet系统变量的最大值相同,即 1073741824 字节(1 GB)。group_replication_communication_max_message_size的设置必须小于replica_max_allowed_packetslave_max_allowed_packet的设置,因为应用程序线程无法处理大于最大允许数据包大小的消息片段。要关闭分段,为group_replication_communication_max_message_size指定零值。

与大多数其他 Group Replication 系统变量一样,必须重新启动 Group Replication 插件才能使更改生效。例如:

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

分段消息的消息传递在所有组成员接收并重新组装消息的所有片段后被视为完成。分段消息在其标头中包含信息,使得在消息传输过程中加入的成员能够恢复其加入之前发送的早期片段。如果加入的成员未能恢复片段,则会自行从组中退出。

为了使复制组使用分片,所有组成员必须在 MySQL 8.0.16 或更高版本,并且组使用的 Group Replication 通信协议版本必须允许分片。您可以使用group_replication_get_communication_protocol()函数检查组使用的通信协议,该函数返回组支持的最旧的 MySQL Server 版本。从 MySQL 5.7.14 版本开始允许消息压缩,从 MySQL 8.0.16 版本开始还允许消息分片。如果所有组成员都在 MySQL 8.0.16 或更高版本,并且没有要求允许早期版本的成员加入,您可以使用group_replication_set_communication_protocol()函数将通信协议版本设置为 MySQL 8.0.16 或更高版本,以允许分片。有关更多信息,请参见第 20.5.1.4 节,“设置组的通信协议版本”。

如果一个复制组由于某些成员不支持而无法使用分片,系统变量group_replication_transaction_size_limit可以用来限制组接受的事务的最大大小。在 MySQL 8.0 中,默认设置约为 143 MB。超过此大小的事务将被回滚。您还可以使用系统变量group_replication_member_expel_timeout来允许额外的时间(最长一小时),在怀疑已经失败的成员被从组中驱逐之前。

20.7.6 XCom 缓存管理

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-performance-xcom-cache.html

20.7.6.1 增加缓存大小

20.7.6.2 减少缓存大小

用于 Group Replication 的组通信引擎(XCom,一种 Paxos 变体)包括一个用于在共识协议的一部分中交换组成员之间的消息(及其元数据)的缓存。消息缓存除了其他功能外,还用于在成员在与其他组成员无法通信的一段时间后重新连接到组时恢复丢失的消息。

从 MySQL 8.0.16 开始,可以使用group_replication_message_cache_size系统变量为 XCom 的消息缓存设置缓存大小限制。如果达到缓存大小限制,XCom 会删除已经决定和传递的最旧条目。因为正在尝试重新连接的不可达成员会随机选择任何其他成员来恢复丢失的消息,所以所有组成员都应该设置相同的缓存大小限制。因此,每个成员的缓存中应该有相同的消息。

在 MySQL 8.0.16 之前,缓存大小为 1 GB,从 MySQL 8.0.16 开始,默认设置的缓存大小相同。请确保系统上有足够的内存可用于您选择的缓存大小限制,考虑到 MySQL Server 的其他缓存和对象池的大小。请注意,使用group_replication_message_cache_size设置的限制仅适用于缓存中存储的数据,缓存结构需要额外的 50 MB 内存。

在选择group_replication_message_cache_size设置时,应参考成员被驱逐之前的时间段内预期的消息量。这段时间的长度由group_replication_member_expel_timeout系统变量控制,该变量确定了等待期限(最长一小时),除了成员最初的 5 秒检测期外,允许成员返回到组中而不被驱逐。请注意,在 MySQL 8.0.21 之前,这段时间默认为成员变得不可用后的 5 秒,这只是在产生怀疑之前的检测期,因为group_replication_member_expel_timeout系统变量设置的额外驱逐超时默认为零。从 8.0.21 开始,驱逐超时默认为 5 秒,因此默认情况下,成员在至少离开 10 秒后才会被驱逐。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-performance-xcom-cache-increase.html

20.7.6.1 增加缓存大小

如果一个成员缺席的时间不够长,以至于还没有被从组中驱逐,它可以重新连接并从另一个成员的 XCom 消息缓存中检索丢失的事务,然后再次参与组。然而,如果在成员缺席期间发生的事务已经被从其他成员的 XCom 消息缓存中删除,因为它们达到了最大大小限制,那么该成员无法通过这种方式重新连接。

Group Replication 的组通信系统(GCS)通过警告消息向您发出警告,当一个消息被从消息缓存中删除时,这个消息可能会被当前不可达的成员用于恢复。这个警告消息被记录在所有活动组成员上(对于每个不可达成员只记录一次)。尽管组成员无法确定不可达成员看到的最后一条消息是什么,但警告消息表明缓存大小可能不足以支持您选择的成员被驱逐之前的等待时间。

在这种情况下,考虑根据group_replication_member_expel_timeout系统变量指定的时间段内预期的消息量,再加上 5 秒的检测期,来增加group_replication_message_cache_size限制,以便缓存包含所有成员成功返回所需的所有丢失消息。如果预计某个成员将在异常时间内变得不可达,还可以考虑暂时增加缓存大小限制。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-performance-xcom-cache-reduce.html

20.7.6.2 减小缓存大小

XCom 消息缓存大小的最小设置是 1 GB,直到 MySQL 8.0.20 版本。从 MySQL 8.0.21 开始,最小设置为 134217728 字节(128 MB),这使得可以在可用内存量受限的主机上部署。如果主机处于不稳定网络上,不建议将group_replication_message_cache_size设置得非常低,因为较小的消息缓存会使组成员在短暂失去连接后更难重新连接。

如果重新连接的成员无法从 XCom 消息缓存中检索到所需的所有消息,则该成员必须离开组并重新加入,以从另一个成员的二进制日志中使用分布式恢复检索缺失的事务。从 MySQL 8.0.21 开始,默认情况下,离开组的成员会进行三次自动重新加入尝试,因此重新加入组的过程可以在没有操作员干预的情况下进行。然而,使用分布式恢复重新加入是一个明显更长且更复杂的过程,比从 XCom 消息缓存中检索消息需要更长时间,因此成员需要更长时间才能变得可用,组的性能可能会受到影响。在稳定网络上,可以最小化成员短暂失去连接的频率和持续时间,因此这种情况发生的频率也应该最小化,因此组可能能够容忍较小的 XCom 消息缓存大小而不会对其性能产生显著影响。

如果您考虑减小缓存大小限制,可以使用以下语句查询 Performance Schema 表memory_summary_global_by_event_name

SELECT * FROM performance_schema.memory_summary_global_by_event_name
  WHERE EVENT_NAME LIKE 'memory/group_rpl/GCS_XCom::xcom_cache';

这返回消息缓存的内存使用统计,包括当前缓存条目数和当前缓存大小。如果您减小缓存大小限制,XCom 会删除已经决定和传递的最旧条目,直到当前大小低于限制。在此移除过程进行时,XCom 可能暂时超过缓存大小限制。

20.7.7 响应故障检测和网络分区

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-responses-failure.html

20.7.7.1 驱逐超时

20.7.7.2 不可达多数超时

20.7.7.3 自动重新加入

20.7.7.4 退出操作

组复制的故障检测机制旨在识别不再与组通信并在看似可能已经失败时将其驱逐的组成员。拥有故障检测机制增加了组包含大多数正常工作成员的机会,因此客户端的请求能够被正确处理。

通常,所有组成员定期与所有其他组成员交换消息。如果某个组成员在 5 秒内没有收到来自特定成员的任何消息,当检测期结束时,会对该成员产生怀疑。当怀疑超时时,被怀疑的成员被认为已经失败,并被驱逐出组。被驱逐的成员从其他成员看到的成员列表中被移除,但它并不知道自己已经被驱逐出组,因此它认为自己在线,而其他成员无法到达。如果成员实际上没有失败(例如,因为仅因临时网络问题而断开连接),并且能够恢复与其他成员的通信,它将接收一个包含其被驱逐出组信息的视图。

组成员对这些情况的响应,包括故障成员本身,在整个过程中可以进行配置。默认情况下,如果怀疑某个成员已经失败,则会发生以下行为:

  1. 在 MySQL 8.0.20 之前,当产生怀疑时,立即超时。一旦组识别到已过期的怀疑,被怀疑的成员就有可能在超时后的几秒内存活,因为定期进行过期怀疑检查。从 MySQL 8.0.21 开始,在怀疑超时并且被怀疑的成员有可能被驱逐之前,会添加 5 秒的等待时间。

  2. 如果被驱逐的成员恢复通信并意识到自己已被驱逐,在 MySQL 8.0.20 之前,它不会尝试重新加入组。从 MySQL 8.0.21 开始,它将自动尝试三次重新加入组(每次尝试之间间隔 5 分钟),如果此自动重新加入过程不起作用,则停止尝试重新加入组。

  3. 当被驱逐的成员不尝试重新加入组时,它会切换到超级只读模式并等待操作员注意。(例外情况是在 MySQL 8.0.12 至 8.0.15 的版本中,默认情况下成员会关闭自身。从 MySQL 8.0.16 开始,行为已更改以匹配 MySQL 5.7 中的行为。)

您可以使用本节中描述的组复制配置选项来永久或临时更改这些行为,以适应您系统的要求和您的优先级。如果您遇到由较慢的网络或机器引起的不必要的驱逐、具有高意外瞬时中断率的网络,或计划中的网络中断,考虑增加驱逐超时和自动重新加入尝试次数。从 MySQL 8.0.21 开始,已更改默认设置以减少在这些情况下需要操作员干预以恢复被驱逐成员的频率。请注意,虽然成员正在经历上述任何默认行为之一时,尽管它不接受写入,但如果成员仍在与客户端通信,则仍然可以进行读取,随着时间的推移,过时读取的可能性会增加。如果避免过时读取对您而言比避免操作员干预更重要,请考虑减少驱逐超时和自动重新加入尝试次数或将其设置为零。

未发生故障的成员可能会由于网络分区而失去与复制组的部分但不是全部的联系。例如,在一个由 5 台服务器(S1、S2、S3、S4、S5)组成的组中,如果(S1、S2)和(S3、S4、S5)之间存在断开连接,则存在网络分区。第一组(S1、S2)现在处于少数派,因为它无法与超过一半的组联系。由少数派组成员处理的任何事务都会被阻塞,因为组的大多数是不可达的,因此组无法达成法定人数。有关此场景的详细描述,请参见第 20.7.8 节,“处理网络分区和法定人数丧失”。在这种情况下,默认行为是使少数派和多数派的成员继续留在组中,继续接受事务(尽管在少数派成员上被阻塞),并等待操作员干预。此行为也是可配置的。

请注意,如果团队成员使用的是较旧的 MySQL 服务器版本,不支持相关设置,或者使用具有不同默认设置的版本,则他们会根据上述默认行为对自己和其他团队成员采取行动。例如,不支持group_replication_member_expel_timeout系统变量的成员会在检测到过期的怀疑时立即驱逐其他成员,并即使其他成员支持该系统变量并设置了更长的超时时间,他们也会接受这种驱逐。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-responses-failure-expel.html

20.7.7.1 驱逐超时

你可以使用group_replication_member_expel_timeout系统变量,该变量从 MySQL 8.0.13 开始提供,以允许在怀疑创建和怀疑成员被驱逐之间提供额外时间。当一个服务器没有从另一个服务器接收消息时,就会创建怀疑,如第 20.1.4.2 节“故障检测”中所解释的那样。

在 Group Replication 组成员创建对另一个成员(或自身)的怀疑之前,会有一个初始的 5 秒检测期。然后,在另一个成员对其(或自身对自身)的怀疑超时后,该组成员将被驱逐。在此之后可能会有一个短暂的时间段,然后驱逐机制会检测并执行驱逐。group_replication_member_expel_timeout指定了在创建怀疑和驱逐被怀疑成员之间等待的时间段,称为驱逐超时,期间组成员被列为UNREACHABLE,但不会从组的成员列表中移除。

  • 如果怀疑成员在等待期结束时再次活动,成员将应用由剩余组成员在 XCom 消息缓存中缓冲的所有消息,并进入ONLINE状态,无需操作员干预。在这种情况下,组将认为该成员是同一实例。

  • 如果怀疑成员在怀疑超时后才重新活动并能恢复通信,它会收到一个被驱逐的视图,此时意识到自己被驱逐。你可以使用group_replication_autorejoin_tries系统变量,该变量从 MySQL 8.0.16 开始提供,使成员在此时自动尝试重新加入组。从 MySQL 8.0.21 开始,默认情况下激活此功能,并且成员会进行三次自动重新加入尝试。如果自动重新加入过程失败或未尝试,则被驱逐成员将按照group_replication_exit_state_action指定的退出操作进行。

在驱逐成员之前的等待时间仅适用于先前在组中活动过的成员。从未在组中活动过的非成员不会获得此等待时间,并且在初始检测期结束后因加入时间过长而被移除。

如果group_replication_member_expel_timeout设置为 0,则没有等待期,而在 5 秒检测期结束后,疑似成员立即有可能被驱逐。这是 MySQL 8.0.20 及更早版本的默认设置。这也是不支持group_replication_member_expel_timeout系统变量的 MySQL 服务器版本的组成员的行为。从 MySQL 8.0.21 开始,默认值为 5,意味着在 5 秒检测期后的 5 秒内,疑似成员有可能被驱逐。并非所有组成员都必须具有相同的group_replication_member_expel_timeout设置,但建议这样做以避免意外驱逐。任何成员都可以对任何其他成员(包括自身)产生怀疑,因此有效的驱逐超时是具有最低设置的成员的超时。

在以下情况下考虑增加group_replication_member_expel_timeout的值,而不使用默认值:

  • 网络速度较慢,默认的 5 或 10 秒在驱逐之前不足以确保组成员始终交换至少一条消息。

  • 网络有时会出现短暂中断,您希望在这些时候避免不必要的驱逐和主要成员更改。

  • 网络不在您的直接控制之下,您希望最大程度减少操作员干预的需求。

  • 预计会发生临时网络中断,您不希望因此而有些或全部成员被驱逐。

  • 个别机器正在经历减速,您不希望它被从组中驱逐。

您可以指定最长达 3600 秒(1 小时)的驱逐超时。重要的是要确保 XCom 的消息缓存足够大,以容纳在指定时间段内预期的消息量,再加上初始的 5 秒检测期,否则成员无法重新连接。您可以使用group_replication_message_cache_size系统变量来调整缓存大小限制。有关更多信息,请参见第 20.7.6 节,“XCom 缓存管理”。

如果一个群组中的任何成员目前受到怀疑,那么群组成员资格不能重新配置(通过添加或删除成员或选举新领导者)。如果需要实施群组成员变更,而其中一个或多个成员受到怀疑,并且你希望怀疑成员继续留在群组中,那么请采取任何必要行动使这些成员重新活跃,如果可能的话。如果你无法使这些成员重新活跃,并且希望将他们从群组中驱逐,你可以立即强制怀疑超时。方法是在任何活跃成员上更改group_replication_member_expel_timeout的值为低于自怀疑创建以来已经经过的时间的值。这样一来,怀疑成员将立即有可能被驱逐。

如果一个复制组成员意外停止并立即重新启动(例如,因为它是使用mysqld_safe启动的),如果设置了group_replication_start_on_boot=on,它会自动尝试重新加入群组。在这种情况下,重新启动和重新加入尝试可能发生在成员的先前实例被驱逐出群组之前,这样该成员就无法重新加入。从 MySQL 8.0.19 开始,Group Replication 自动使用群组通信系统(GCS)功能为成员重试重新加入尝试 10 次,每次重试之间间隔 5 秒。这应该涵盖大多数情况,并允许足够的时间让先前的实例被驱逐出群组,从而让成员重新加入。请注意,如果group_replication_member_expel_timeout系统变量设置为指定成员被驱逐之前等待的较长时间,自动重新加入尝试可能仍然不会成功。

对于在group_replication_member_expel_timeout系统变量不可用的情况下避免不必要驱逐的替代缓解策略,请参阅 Section 20.3.2, “Group Replication Limitations”。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-responses-failure-partition.html

20.7.7.2 不可达多数超时

默认情况下,由于网络分区而处于少数派的成员不会自动离开群组。您可以使用系统变量group_replication_unreachable_majority_timeout设置成员在与大多数群组成员失去联系后等待的秒数,然后退出群组。设置超时意味着您无需主动监视网络分区后处于少数派群组的服务器,并且可以避免由于不当干预而创建群组成员的两个版本导致的分裂脑情况。

group_replication_unreachable_majority_timeout指定的超时时间到期时,已由该成员和少数派群组中的其他成员处理的所有待处理事务都将被回滚,并且该群组中的服务器将移至ERROR状态。您可以使用从 MySQL 8.0.16 开始提供的group_replication_autorejoin_tries系统变量,使成员在此时自动尝试重新加入群组。从 MySQL 8.0.21 开始,默认情况下激活此功能,并且成员将进行三次自动重新加入尝试。如果自动重新加入过程不成功或未尝试,则少数派成员将按照group_replication_exit_state_action指定的退出操作进行。

在决定是否设置不可达多数超时时,请考虑以下几点:

  • 在对称群组中,例如具有两个或四个服务器的群组,如果两个分区包含相等数量的服务器,则两个群组都认为自己处于少数派并进入ERROR状态。在这种情况下,群组没有功能性分区。

  • 尽管存在少数派群组,但由少数派群组处理的任何事务都会被接受,但由于少数服务器无法达到法定人数,这些事务被阻塞,直到在这些服务器上发出STOP GROUP_REPLICATION或达到不可达多数超时为止。

  • 如果不设置不可达多数超时,则少数派群组中的服务器永远不会自动进入ERROR状态,您必须手动停止它们。

  • 如果在检测到大多数丢失后在少数派群组的服务器上设置不可达多数超时,则不会产生任何影响。

如果您不使用group_replication_unreachable_majority_timeout系统变量,则在网络分区事件中进行操作发明的过程在第 20.7.8 节,“处理网络分区和失去法定人数”中描述。该过程涉及检查哪些服务器正在运行,并在必要时强制进行新的组成员资格。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-responses-failure-rejoin.html

20.7.7.3 自动重新加入

group_replication_autorejoin_tries系统变量从 MySQL 8.0.16 开始提供,使被驱逐或达到不可达多数超时的成员尝试自动重新加入组。在 MySQL 8.0.20 之前,系统变量的值默认为 0,因此默认情况下不会激活自动重新加入。从 MySQL 8.0.21 开始,系统变量的值默认为 3,这意味着成员会自动尝试重新加入组,每次尝试之间间隔 5 分钟,最多尝试 3 次。

当未激活自动重新加入时,成员一旦恢复通信即接受其驱逐,并继续执行由group_replication_exit_state_action系统变量指定的操作。之后,需要手动干预才能将成员带回组中。如果您可以容忍可能出现过时读取的可能性,并希望最小化手动干预的需求,特别是在瞬时网络问题经常导致成员被驱逐的情况下,使用自动重新加入功能是合适的。

使用自动重新加入时,当成员被驱逐或达到不可达多数超时时,它会尝试重新加入(使用当前插件选项值),然后继续进行进一步的自动重新加入尝试,直到达到指定的尝试次数为止。在一次不成功的自动重新加入尝试后,成员在下一次尝试之前等待 5 分钟。自动重新加入尝试和它们之间的时间称为自动重新加入过程。如果在成员重新加入或停止之前耗尽了指定的尝试次数,则成员将执行由group_replication_exit_state_action系统变量指定的操作。

在自动重新加入尝试期间和之间,成员保持在超级只读模式,并在其复制组视图上显示ERROR状态。在此期间,成员不接受写入。但是,随着时间的推移,成员上的读取仍然可以进行,但随着时间的推移,读取变得越来越可能过时。如果您确实希望在自动重新加入过程中干预以使成员脱机,可以随时使用STOP GROUP_REPLICATION语句或关闭服务器来手动停止成员。如果您无法容忍任何时间段内可能出现过时读取的可能性,请将group_replication_autorejoin_tries系统变量设置为 0。

你可以使用性能模式监视自动重新加入过程。在自动重新加入过程进行时,性能模式表events_stages_current显示事件“正在进行自动重新加入过程”,显示到目前为止在此过程实例中尝试的重试次数(在WORK_COMPLETED字段中)。events_stages_summary_global_by_event_name表显示服务器实例启动自动重新加入过程的次数(在COUNT_STAR字段中)。events_stages_history_long表显示每个自动重新加入过程完成的时间(在TIMER_END字段中)。当成员重新加入复制组时,在组完成兼容性检查并接受其为成员之前,其状态可能显示为OFFLINEERROR。当成员正在赶上组的事务时,其状态为RECOVERING

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-responses-failure-exit.html

20.7.7.4 退出操作

group_replication_exit_state_action系统变量,从 MySQL 8.0.12 和 MySQL 5.7.24 开始提供,指定了当成员由于错误或问题意外离开组时,Group Replication 应该执行的操作,以及在自动重新加入失败或不尝试重新加入时的操作。请注意,在被驱逐成员的情况下,成员在重新连接到组之前并不知道自己被驱逐,因此只有在成员成功重新连接或成员对自己产生怀疑并将自己驱逐时,才会执行指定的操作。

按影响顺序,退出操作如下:

  1. 如果READ_ONLY是退出操作,实例将通过将系统变量super_read_only设置为ON,将 MySQL 切换到超级只读模式。当成员处于超级只读模式时,客户端无法进行任何更新操作,即使他们拥有CONNECTION_ADMIN权限(或已弃用的SUPER权限)。然而,客户端仍然可以读取数据,由于不再进行更新,随着时间的推移,存在过时读取的可能性会增加。因此,您需要主动监视服务器以防止故障。从 MySQL 8.0.15 开始,这是默认的退出操作。在执行此退出操作后,成员的状态将在组的视图中显示为ERROR

  2. 如果OFFLINE_MODE是退出操作,则通过将系统变量offline_mode设置为ON,实例将将 MySQL 切换到离线模式。当成员处于离线模式时,连接的客户端用户在下一次请求时将被断开连接,不再接受连接,但具有CONNECTION_ADMIN权限(或已弃用的SUPER权限)的客户端用户除外。Group Replication 还将系统变量super_read_only设置为ON,因此客户端无法进行任何更新,即使他们已经使用CONNECTION_ADMINSUPER权限连接。此退出操作阻止了更新和过时读取(除了具有上述权限的客户端用户进行读取),并使代理工具(如 MySQL Router)能够识别服务器不可用并重定向客户端连接。它还保持实例运行,以便管理员可以尝试解决问题而不关闭 MySQL。此退出操作从 MySQL 8.0.18 版本开始提供。在执行此退出操作后,成员的状态在组的视图中显示为ERROR(而不是OFFLINE,这意味着成员具有 Group Replication 功能,但当前不属于任何组)。

  3. 如果ABORT_SERVER是退出操作,则实例将关闭 MySQL。指示成员关闭自身可以防止所有过时读取和客户端更新,但这意味着 MySQL Server 实例不可用,必须重新启动,即使问题可以在不进行此步骤的情况下解决。此退出操作是从 MySQL 8.0.12 版本(添加系统变量时)到 MySQL 8.0.15 版本(含)的默认操作。在执行此退出操作后,成员将从组的视图中的服务器列表中删除。

请注意,无论设置了哪种退出操作,都需要操作员干预,因为已耗尽自动重新加入尝试(或从未有过)并已被组驱逐的前成员不允许重新加入而无需重新启动 Group Replication。退出操作仅影响客户端是否仍然可以在无法重新加入组的服务器上读取数据,以及服务器是否保持运行。

重要提示

如果在成员成功加入组之前发生故障,则不会执行group_replication_exit_state_action指定的退出操作。这种情况发生在本地配置检查期间发生故障,或者加入成员的配置与组的配置不匹配时。在这些情况下,super_read_only系统变量保持其原始值,服务器不会关闭 MySQL。为了确保当 Group Replication 未启动时服务器无法接受更新,我们建议在服务器启动时在配置文件中设置super_read_only=ON,Group Replication 在成功启动后将其更改为OFF。当服务器配置为在服务器启动时启动 Group Replication(group_replication_start_on_boot=ON)时,此保护措施尤为重要,但在使用START GROUP_REPLICATION命令手动启动 Group Replication 时也很有用。

如果成员成功加入组后发生故障,则执行指定的退出操作。以下情况会发生:

  1. 应用程序错误 - 复制应用程序中存在错误。此问题无法恢复。

  2. 无法进行分布式恢复 - 存在问题,导致 Group Replication 的分布式恢复过程(使用远程克隆操作和从二进制日志进行状态传输)无法完成。Group Replication 在适当的情况下会自动重试分布式恢复,但如果没有更多选项来完成该过程,则会停止。有关详细信息,请参见第 20.5.4.4 节,“分布式恢复的容错性”。

  3. 组配置更改错误 - 在使用函数进行组范围配置更改时发生错误,如第 20.5.1 节,“配置在线组”中所述。

  4. 主选举错误 - 在单主模式下为组选择新主成员时发生错误,如第 20.1.3.1 节,“单主模式”中所述。

  5. 无法访问的多数超时 - 成员与大多数组成员失去联系,因此处于少数,并且由 group_replication_unreachable_majority_timeout 系统变量设置的超时已经过期。

  6. 成员被组驱逐 - 对成员提出了怀疑,并且由 group_replication_member_expel_timeout 系统变量设置的任何超时已经过期,成员已恢复与组的通信并发现自己已被驱逐。

  7. 超出自动重新加入尝试次数 - group_replication_autorejoin_tries 系统变量被设置为指定在失去多数或被驱逐后的自动重新加入尝试次数,成员完成了这些尝试次数但未成功。

以下表格总结了每种情况下的失败场景和操作:

表 20.3 组复制失败情况下的退出操作

失败情况 使用 START GROUP_REPLICATION 启动组复制 使用 group_replication_start_on_boot =ON 启动组复制
成员未通过本地配置检查加入成员与组配置不匹配 super_read_onlyoffline_mode 未更改 MySQL 继续运行在启动时设置 super_read_only=ON 以防止更新 super_read_onlyoffline_mode 未更改 MySQL 继续运行在启动时设置 super_read_only=ON 以防止更新(重要)
应用程序错误在成员分布式恢复不可能组配置更改错误主要选举错误无法访问的多数超时成员被组驱逐超出自动重新加入尝试次数 super_read_only 设置为 ONoffline_modesuper_read_only 设置为 ON 或 MySQL 关闭 super_read_only 设置为 ONoffline_modesuper_read_only 设置为 ON 或 MySQL 关闭

20.7.8 处理网络分区和失去法定人数

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-network-partitioning.html

当需要复制发生的更改时,组需要达成共识。这适用于常规事务,但也适用于组成员更改和保持组一致性的某些内部消息。共识要求组成员中的大多数同意给定决定。当组成员的大多数丢失时,组无法继续进行并阻塞,因为它无法获得法定人数或法定人数。

当有多个非自愿故障导致大多数服务器突然从组中移除时,可能会丢失法定人数。例如,在 5 台服务器组中,如果其中有 3 台同时变得沉默,那么大多数就会受到影响,因此无法实现法定人数。事实上,剩下的两台无法确定其他 3 台服务器是否已崩溃,还是网络分区已将这两台孤立,因此组无法自动重新配置。

另一方面,如果服务器自愿退出组,它们会指示组应重新配置自身。实际上,这意味着要离开的服务器告诉其他人它要离开。这意味着其他成员可以正确地重新配置组,维护成员的一致性并重新计算法定人数。例如,在上述 5 台服务器的情况下,如果有 3 台同时离开,如果这 3 台离开的服务器依次警告组它们要离开,那么成员资格就能够从 5 调整到 2,并同时在此过程中确保法定人数。

注意

失去法定人数本身就是规划不良的副作用。根据预期故障数量规划组大小(无论这些故障是连续发生、同时发生还是零星发生)。

对于单主模式的组,主服务器可能有一些尚未在网络分区发生时其他成员上出现的事务。如果考虑将主服务器排除在新组之外,请注意这些事务可能会丢失。具有额外事务的成员无法重新加入组,尝试会导致错误消息,内容为此成员的已执行事务多于组中存在的事务。设置group_replication_unreachable_majority_timeout系统变量以避免此情况。

以下各节解释了如果系统以使组内服务器无法自动实现法定人数的方式分区应该怎么办。

检测分区

replication_group_members 性能模式表呈现了从该服务器的视角看到的当前视图中每台服务器的状态。大多数情况下,系统不会遇到分区,因此该表显示跨组中所有服务器一致的信息。换句话说,该表上每台服务器的状态在当前视图中得到了所有人的认可。然而,如果存在网络分区,并且丢失了法定人数,那么对于那些无法联系的服务器,该表将显示状态为 UNREACHABLE。这些信息由 Group Replication 内置的本地故障检测器导出。

图 20.14 失去法定人数

五个服务器实例,S1、S2、S3、S4 和 S5,部署为一个相互连接的稳定组。当其中三台服务器 S3、S4 和 S5 失效时,大多数失去,组无法在没有干预的情况下继续运行。

要理解这种类型的网络分区,以下部分描述了最初有 5 台服务器正确协作的情景,以及一旦只有 2 台服务器在线后组发生的变化。该情景在图中描述。

因此,假设有一个包含这 5 台服务器的组:

  • 服务器 s1 的成员标识符为 199b2df7-4aaf-11e6-bb16-28b2bd168d07

  • 服务器 s2 的成员标识符为 199bb88e-4aaf-11e6-babe-28b2bd168d07

  • 服务器 s3 的成员标识符为 1999b9fb-4aaf-11e6-bb54-28b2bd168d07

  • 服务器 s4 的成员标识符为 19ab72fc-4aaf-11e6-bb51-28b2bd168d07

  • 服务器 s5 的成员标识符为 19b33846-4aaf-11e6-ba81-28b2bd168d07

最初,组运行良好,服务器之间愉快地进行通信。您可以通过登录 s1 并查看其 replication_group_members 性能模式表来验证这一点。例如:

mysql> SELECT MEMBER_ID,MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+-------------+
| MEMBER_ID                            | MEMBER_STATE | MEMBER_ROLE |
+--------------------------------------+--------------+-------------+
| 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | ONLINE       | SECONDARY   |
| 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | ONLINE       | PRIMARY     |
| 199bb88e-4aaf-11e6-babe-28b2bd168d07 | ONLINE       | SECONDARY   |
| 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | ONLINE       | SECONDARY   |
| 19b33846-4aaf-11e6-ba81-28b2bd168d07 | ONLINE       | SECONDARY   |
+--------------------------------------+--------------+-------------+

然而,片刻之后发生了灾难性故障,服务器 s3、s4 和 s5 意外停止运行。几秒钟后,再次查看 s1 上的 replication_group_members 表,显示它仍然在线,但其他几个成员不在线。事实上,如下所示,它们被标记为 UNREACHABLE。此外,系统无法重新配置自身以更改成员资格,因为大多数成员已经丢失。

mysql> SELECT MEMBER_ID,MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID                            | MEMBER_STATE |
+--------------------------------------+--------------+
| 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | UNREACHABLE  |
| 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | ONLINE       |
| 199bb88e-4aaf-11e6-babe-28b2bd168d07 | ONLINE       |
| 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | UNREACHABLE  |
| 19b33846-4aaf-11e6-ba81-28b2bd168d07 | UNREACHABLE  |
+--------------------------------------+--------------+

表格显示,s1 现在处于一个没有办法继续进行的组中,因为大多数服务器无法访问。在这种特殊情况下,需要重置组成员列表以允许系统继续进行,这在本节中有解释。或者,您也可以选择停止 s1 和 s2 上的组复制(或完全停止 s1 和 s2),弄清楚 s3、s4 和 s5 发生了什么,然后重新启动组复制(或服务器)。

解除分区阻塞

组复制使您能够通过强制特定配置来重置组成员列表。例如,在上述情况中,只有 s1 和 s2 在线,您可以选择强制执行仅包含 s1 和 s2 的成员配置。这需要检查有关 s1 和 s2 的一些信息,然后使用 group_replication_force_members 变量。

图 20.15 强制执行新的成员配置

组中的三台服务器 S3、S4 和 S5 失败,因此失去了多数派,组无法继续进行。通过下文描述的干预,S1 和 S2 能够自行形成一个稳定的组。

假设您回到了只剩下 s1 和 s2 两台服务器的情况。服务器 s3、s4 和 s5 突然离开了组。为了让服务器 s1 和 s2 继续运行,您希望强制执行一个只包含 s1 和 s2 的成员配置。

警告

此过程使用 group_replication_force_members ,应被视为最后的补救措施。它必须极度小心使用,仅用于覆盖丧失法定人数的情况。如果被滥用,可能会导致人为的脑裂情况或完全阻塞整个系统。

在强制执行新的成员配置时,请确保任何要被强制退出组的服务器确实已经停止运行。在上述场景中,如果 s3、s4 和 s5 并非真正无法访问,而是在线的话,它们可能已经形成了自己的功能分区(它们是 5 台中的 3 台,因此拥有多数派)。在这种情况下,强制使用只包含 s1 和 s2 的组成员列表可能会导致人为的脑裂情况。因此,在强制执行新的成员配置之前,确保要排除的服务器确实已关闭,如果没有关闭,请在继续之前关闭它们。

警告

对于单主模式的组,主服务器可能有一些在网络分区时其他成员尚未存在的事务。如果您考虑将主服务器排除在新组之外,请注意这些事务可能会丢失。具有额外事务的成员无法重新加入组,尝试会导致错误消息为此成员的已执行事务多于组中存在的事务。设置group_replication_unreachable_majority_timeout系统变量以避免此情况。

请记住系统被阻塞,当前配置如下(由s1上的本地故障检测器感知):

mysql> SELECT MEMBER_ID,MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID                            | MEMBER_STATE |
+--------------------------------------+--------------+
| 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | UNREACHABLE  |
| 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | ONLINE       |
| 199bb88e-4aaf-11e6-babe-28b2bd168d07 | ONLINE       |
| 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | UNREACHABLE  |
| 19b33846-4aaf-11e6-ba81-28b2bd168d07 | UNREACHABLE  |
+--------------------------------------+--------------+

首先要做的是检查s1s2的本地地址(组通信标识符)。登录到s1s2,并按以下方式获取该信息。

mysql> SELECT @@group_replication_local_address;

一旦知道s1127.0.0.1:10000)和s2127.0.0.1:10001)的组通信地址,您可以在两个服务器中的一个上使用它来注入新的成员配置,从而覆盖已失去法定人数的现有配置。在s1上执行以下操作:

mysql> SET GLOBAL group_replication_force_members="127.0.0.1:10000,127.0.0.1:10001";

通过强制不同配置来解除组的阻塞。在此更改后,检查s1s2上的replication_group_members以验证组成员身份。首先在s1上。

mysql> SELECT MEMBER_ID,MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID                            | MEMBER_STATE |
+--------------------------------------+--------------+
| b5ffe505-4ab6-11e6-b04b-28b2bd168d07 | ONLINE       |
| b60907e7-4ab6-11e6-afb7-28b2bd168d07 | ONLINE       |
+--------------------------------------+--------------+

然后在s2上执行。

mysql> SELECT * FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID                            | MEMBER_STATE |
+--------------------------------------+--------------+
| b5ffe505-4ab6-11e6-b04b-28b2bd168d07 | ONLINE       |
| b60907e7-4ab6-11e6-afb7-28b2bd168d07 | ONLINE       |
+--------------------------------------+--------------+

在使用group_replication_force_members系统变量成功强制新的组成员身份并解除组阻塞后,请确保清除该系统变量。为了发出START GROUP_REPLICATION语句,group_replication_force_members必须为空。

20.7.9 使用 Performance Schema 内存仪表化监控 Group Replication 内存使用情况

原文:dev.mysql.com/doc/refman/8.0/en/mysql-gr-memory-monitoring-ps-instruments.html

20.7.9.1 启用或禁用 Group Replication 仪表化

20.7.9.2 示例查询

从 MySQL 8.0.30 开始,Performance Schema 提供了用于监控 Group Replication 内存使用情况的仪表化。要查看可用的 Group Replication 仪表,执行以下查询:

mysql> SELECT NAME,ENABLED FROM performance_schema.setup_instruments
       WHERE NAME LIKE 'memory/group_rpl/%';
+-------------------------------------------------------------------+---------+
| NAME                                                              | ENABLED |
+-------------------------------------------------------------------+---------+
| memory/group_rpl/write_set_encoded                                | YES     |
| memory/group_rpl/certification_data                               | YES     |
| memory/group_rpl/certification_data_gc                            | YES     |
| memory/group_rpl/certification_info                               | YES     |
| memory/group_rpl/transaction_data                                 | YES     |
| memory/group_rpl/sql_service_command_data                         | YES     |
| memory/group_rpl/mysql_thread_queued_task                         | YES     |
| memory/group_rpl/message_service_queue                            | YES     |
| memory/group_rpl/message_service_received_message                 | YES     |
| memory/group_rpl/group_member_info                                | YES     |
| memory/group_rpl/consistent_members_that_must_prepare_transaction | YES     |
| memory/group_rpl/consistent_transactions                          | YES     |
| memory/group_rpl/consistent_transactions_prepared                 | YES     |
| memory/group_rpl/consistent_transactions_waiting                  | YES     |
| memory/group_rpl/consistent_transactions_delayed_view_change      | YES     |
| memory/group_rpl/GCS_XCom::xcom_cache                             | YES     |
| memory/group_rpl/Gcs_message_data::m_buffer                       | YES     |
+-------------------------------------------------------------------+---------+

有关 Performance Schema 内存仪表化和事件的更多信息,请参阅 第 29.12.20.10 节,“内存摘要表”。

Performance Schema Group Replication 为 Group Replication 的内存分配提供仪表化。

memory/group_rpl/ Performance Schema 仪表化在 8.0.30 中进行了更新,以扩展对 Group Replication 内存使用情况的监控。memory/group_rpl/ 包含以下仪表:

  • write_set_encoded: 在广播到组成员之前对写入集进行编码分配的内存。

  • Gcs_message_data::m_buffer: 为发送到网络的事务数据负载分配的内存。

  • certification_data: 为传入事务的认证分配的内存。

  • certification_data_gc: 为每个成员发送的 GTID_EXECUTED 进行垃圾回收分配的内存。

  • certification_info: 为解决并发事务之间冲突分配的认证信息存储内存。

  • transaction_data: 为排队等待插件管道的传入事务分配的内存。

  • message_service_received_message: 为从 Group Replication 传递消息服务接收消息分配的内存。

  • sql_service_command_data: 为处理内部 SQL 服务命令队列分配的内存。

  • mysql_thread_queued_task: 当将 MySQL 线程相关任务添加到处理队列时分配的内存。

  • message_service_queue: 为 Group Replication 传递消息服务的排队消息分配的内存。

  • GCS_XCom::xcom_cache: 为组成员之间作为共识协议的一部分交换的消息和元数据分配的 XCOM 缓存内存。

  • consistent_members_that_must_prepare_transaction: 为保存为 Group Replication 事务一致性保证准备事务的成员列表分配的内存。

  • consistent_transactions: 为保存事务和必须为 Group Replication 事务一致性保证准备该事务的成员列表分配的内存。

  • consistent_transactions_prepared: 为保存为 Group Replication 事务一致性保证准备的事务信息列表分配的内存。

  • consistent_transactions_waiting:用于保存在处理具有AFTERBEFORE_AND_AFTER一致性的准备事务之前的事务列表信息的内存分配。

  • consistent_transactions_delayed_view_change:用于保存由于准备一致性事务等待准备确认而延迟的视图更改事件(view_change_log_event)列表的内存分配。

  • group_member_info:用于保存组成员属性的内存分配。属性如主机名、端口、成员权重和角色等。

memory/sql/ 分组中的以下工具也用于监视组复制内存:

  • Log_event:用于将事务数据编码为二进制日志格式的内存分配;这是组复制传输数据的相同格式。

  • write_set_extraction:在提交之前为事务生成的写入集分配的内存。

  • Gtid_set::to_string:用于存储 GTID 集合的字符串表示的内存分配。

  • Gtid_set::Interval_chunk:用于存储 GTID 对象的内存分配。

原文:dev.mysql.com/doc/refman/8.0/en/mysql-gr-memory-monitoring-ps-instruments-enable.html

20.7.9.1 启用或禁用组复制仪器

要从命令行启用所有组复制仪器,请在您选择的 SQL 客户端中运行以下命令:

 UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' 
        WHERE NAME LIKE 'memory/group_rpl/%';

要从命令行禁用所有组复制仪器,请在您选择的 SQL 客户端中运行以下命令:

 UPDATE performance_schema.setup_instruments SET ENABLED = 'NO' 
        WHERE NAME LIKE 'memory/group_rpl/%';

要在服务器启动时启用所有组复制仪器,请将以下内容添加到您的选项文件中:

 [mysqld]
 performance-schema-instrument='memory/group_rpl/%=ON'

要在服务器启动时禁用所有组复制仪器,请将以下内容添加到您的选项文件中:

 [mysqld]
 performance-schema-instrument='memory/group_rpl/%=OFF'

要启用或禁用该组中的单个仪器,请用该仪器的全名替换通配符(%)。

欲了解更多信息,请参阅 Section 29.3, “性能模式启动配置”和 Section 29.4, “性能模式运行时配置”。

原文:dev.mysql.com/doc/refman/8.0/en/mysql-gr-memory-monitoring-ps-sample-queries.html

20.7.9.2 示例查询

本节描述了使用工具和事件监视组复制内存使用情况的示例查询。这些查询从memory_summary_global_by_event_name表中检索数据。

内存数据可以查询单个事件,例如:

SELECT * FROM performance_schema.memory_summary_global_by_event_name
WHERE EVENT_NAME = 'memory/group_rpl/write_set_encoded'\G

*************************** 1\. row ***************************
                  EVENT_NAME: memory/group_rpl/write_set_encoded
                 COUNT_ALLOC: 1
                  COUNT_FREE: 0
   SUM_NUMBER_OF_BYTES_ALLOC: 45
    SUM_NUMBER_OF_BYTES_FREE: 0
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 1
             HIGH_COUNT_USED: 1
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 45
   HIGH_NUMBER_OF_BYTES_USED: 45

更多关于列的信息,请参阅第 29.12.20.10 节,“内存摘要表”。

您还可以定义查询,对各种事件求和,以提供特定内存使用领域的概述。

下面描述了以下示例:

  • 用于捕获事务的内存

  • 用于广播事务的内存

  • 组复制中的总内存使用量

  • 认证中使用的内存

  • 认证中使用的内存

  • 复制管道中使用的内存

  • 一致性中使用的内存

  • 交付消息服务中使用的内存

  • 用于广播和接收事务的内存

记忆用于捕获事务

用于捕获用户事务的内存分配是write_set_encodedwrite_set_extractionLog_event事件值的总和。例如:

 mysql> SELECT * FROM (
                   SELECT
                     (CASE
                        WHEN EVENT_NAME LIKE 'memory/group_rpl/write_set_encoded'
                        THEN 'memory/group_rpl/memory_gr'
                        WHEN EVENT_NAME = 'memory/sql/write_set_extraction'
                        THEN 'memory/group_rpl/memory_gr'
                        WHEN EVENT_NAME = 'memory/sql/Log_event'
                        THEN 'memory/group_rpl/memory_gr'
                        ELSE 'memory_gr_rest'
                     END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
                   SUM(SUM_NUMBER_OF_BYTES_ALLOC),
                   SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
                   SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
                   SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
                   SUM(HIGH_NUMBER_OF_BYTES_USED)
                 FROM performance_schema.memory_summary_global_by_event_name
                 GROUP BY (CASE
                              WHEN EVENT_NAME LIKE 'memory/group_rpl/write_set_encoded'
                              THEN 'memory/group_rpl/memory_gr'
                              WHEN EVENT_NAME = 'memory/sql/write_set_extraction'
                              THEN 'memory/group_rpl/memory_gr'
                              WHEN EVENT_NAME = 'memory/sql/Log_event'
                              THEN 'memory/group_rpl/memory_gr'
                              ELSE 'memory_gr_rest'
                            END)
      ) f
      WHERE f.EVENT_NAME != 'memory_gr_rest'
      *************************** 1\. row ***************************
                             EVENT_NAME: memory/group_rpl/memory_gr
                       SUM(COUNT_ALLOC): 127
                        SUM(COUNT_FREE): 117
         SUM(SUM_NUMBER_OF_BYTES_ALLOC): 54808
          SUM(SUM_NUMBER_OF_BYTES_FREE): 52051
                    SUM(LOW_COUNT_USED): 0
                SUM(CURRENT_COUNT_USED): 10
                   SUM(HIGH_COUNT_USED): 35
          SUM(LOW_NUMBER_OF_BYTES_USED): 0
      SUM(CURRENT_NUMBER_OF_BYTES_USED): 2757
         SUM(HIGH_NUMBER_OF_BYTES_USED): 15630
记忆用于广播事务

用于广播事务的内存分配是Gcs_message_data::m_buffertransaction_dataGCS_XCom::xcom_cache事件值的总和。例如:

 mysql> SELECT * FROM (
                  SELECT
                    (CASE
                       WHEN EVENT_NAME =  'memory/group_rpl/Gcs_message_data::m_buffer'
                       THEN 'memory/group_rpl/memory_gr'
                       WHEN EVENT_NAME = 'memory/group_rpl/GCS_XCom::xcom_cache'
                       THEN 'memory/group_rpl/memory_gr'
                       WHEN EVENT_NAME = 'memory/group_rpl/transaction_data'
                       THEN 'memory/group_rpl/memory_gr'
                       ELSE 'memory_gr_rest'
                    END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
                    SUM(SUM_NUMBER_OF_BYTES_ALLOC),
                    SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
                    SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
                    SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
                    SUM(HIGH_NUMBER_OF_BYTES_USED)
                  FROM performance_schema.memory_summary_global_by_event_name
                  GROUP BY (CASE
                              WHEN EVENT_NAME =  'memory/group_rpl/Gcs_message_data::m_buffer'
                              THEN 'memory/group_rpl/memory_gr'
                              WHEN EVENT_NAME = 'memory/group_rpl/GCS_XCom::xcom_cache'
                              THEN 'memory/group_rpl/memory_gr'
                              WHEN EVENT_NAME = 'memory/group_rpl/transaction_data'
                              THEN 'memory/group_rpl/memory_gr'
                              ELSE 'memory_gr_rest'
                            END)
       ) f
       WHERE f.EVENT_NAME != 'memory_gr_rest'\G
       *************************** 1\. row ***************************
                              EVENT_NAME: memory/group_rpl/memory_gr
                        SUM(COUNT_ALLOC): 84
                         SUM(COUNT_FREE): 31
          SUM(SUM_NUMBER_OF_BYTES_ALLOC): 1072324
           SUM(SUM_NUMBER_OF_BYTES_FREE): 7149
                     SUM(LOW_COUNT_USED): 0
                 SUM(CURRENT_COUNT_USED): 53
                    SUM(HIGH_COUNT_USED): 59
           SUM(LOW_NUMBER_OF_BYTES_USED): 0
       SUM(CURRENT_NUMBER_OF_BYTES_USED): 1065175
          SUM(HIGH_NUMBER_OF_BYTES_USED): 1065809
在组复制中使用的总内存

用于发送和接收事务、认证和所有其他主要进程的内存分配。通过查询memory/group_rpl/组的所有事件来计算。例如:

 mysql> SELECT * FROM (
                  SELECT
                    (CASE
                       WHEN EVENT_NAME LIKE 'memory/group_rpl/%'
                       THEN 'memory/group_rpl/memory_gr'
                       ELSE 'memory_gr_rest'
                     END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
                     SUM(SUM_NUMBER_OF_BYTES_ALLOC),
                     SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
                     SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
                     SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
                     SUM(HIGH_NUMBER_OF_BYTES_USED)
                  FROM performance_schema.memory_summary_global_by_event_name
                  GROUP BY (CASE
                              WHEN EVENT_NAME LIKE 'memory/group_rpl/%'
                              THEN 'memory/group_rpl/memory_gr'
                              ELSE 'memory_gr_rest'
                            END)
       ) f
       WHERE f.EVENT_NAME != 'memory_gr_rest'\G
       *************************** 1\. row ***************************
                              EVENT_NAME: memory/group_rpl/memory_gr
                        SUM(COUNT_ALLOC): 190
                         SUM(COUNT_FREE): 127
          SUM(SUM_NUMBER_OF_BYTES_ALLOC): 1096370
           SUM(SUM_NUMBER_OF_BYTES_FREE): 28675
                     SUM(LOW_COUNT_USED): 0
                 SUM(CURRENT_COUNT_USED): 63
                    SUM(HIGH_COUNT_USED): 77
           SUM(LOW_NUMBER_OF_BYTES_USED): 0
       SUM(CURRENT_NUMBER_OF_BYTES_USED): 1067695
          SUM(HIGH_NUMBER_OF_BYTES_USED): 1069255
认证中使用的内存

认证过程中的内存分配是certification_datacertification_data_gccertification_info事件值的总和。例如:

 mysql> SELECT * FROM (
                  SELECT
                    (CASE
                       WHEN EVENT_NAME = 'memory/group_rpl/certification_data'
                       THEN 'memory/group_rpl/certification'
                       WHEN EVENT_NAME = 'memory/group_rpl/certification_data_gc'
                       THEN 'memory/group_rpl/certification'
                       WHEN EVENT_NAME = 'memory/group_rpl/certification_info'
                       THEN 'memory/group_rpl/certification'
                       ELSE 'memory_gr_rest'
                     END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
                     SUM(SUM_NUMBER_OF_BYTES_ALLOC),
                     SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
                     SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
                     SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
                     SUM(HIGH_NUMBER_OF_BYTES_USED)
                  FROM performance_schema.memory_summary_global_by_event_name
                  GROUP BY (CASE
                              WHEN EVENT_NAME = 'memory/group_rpl/certification_data'
                              THEN 'memory/group_rpl/certification'
                              WHEN EVENT_NAME = 'memory/group_rpl/certification_data_gc'
                              THEN 'memory/group_rpl/certification'
                              WHEN EVENT_NAME = 'memory/group_rpl/certification_info'
                              THEN 'memory/group_rpl/certification'
                              ELSE 'memory_gr_rest'
                           END)
       ) f
       WHERE f.EVENT_NAME != 'memory_gr_rest'\G
       *************************** 1\. row ***************************
                              EVENT_NAME: memory/group_rpl/certification
                        SUM(COUNT_ALLOC): 80
                         SUM(COUNT_FREE): 80
          SUM(SUM_NUMBER_OF_BYTES_ALLOC): 9442
           SUM(SUM_NUMBER_OF_BYTES_FREE): 9442
                     SUM(LOW_COUNT_USED): 0
                 SUM(CURRENT_COUNT_USED): 0
                    SUM(HIGH_COUNT_USED): 66
           SUM(LOW_NUMBER_OF_BYTES_USED): 0
       SUM(CURRENT_NUMBER_OF_BYTES_USED): 0
          SUM(HIGH_NUMBER_OF_BYTES_USED): 6561
复制管道中使用的内存

复制管道的内存分配是certification_datatransaction_data事件值的总和。例如:

 mysql> SELECT * FROM (
                  SELECT
                    (CASE
                       WHEN EVENT_NAME LIKE 'memory/group_rpl/certification_data'
                       THEN 'memory/group_rpl/pipeline'
                       WHEN EVENT_NAME LIKE 'memory/group_rpl/transaction_data'
                       THEN 'memory/group_rpl/pipeline'
                       ELSE 'memory_gr_rest'
                     END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
                     SUM(SUM_NUMBER_OF_BYTES_ALLOC),
                     SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
                     SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
                     SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
                     SUM(HIGH_NUMBER_OF_BYTES_USED)
                   FROM performance_schema.memory_summary_global_by_event_name
                   GROUP BY (CASE
                              WHEN EVENT_NAME LIKE 'memory/group_rpl/certification_data'
                              THEN 'memory/group_rpl/pipeline'
                              WHEN EVENT_NAME LIKE 'memory/group_rpl/transaction_data'
                              THEN 'memory/group_rpl/pipeline'
                              ELSE 'memory_gr_rest'
                            END)
       ) f
       WHERE f.EVENT_NAME != 'memory_gr_rest'\G
       *************************** 1\. row ***************************
                         EVENT_NAME: memory/group_rpl/pipeline
                        COUNT_ALLOC: 17
                         COUNT_FREE: 13
          SUM_NUMBER_OF_BYTES_ALLOC: 2483
           SUM_NUMBER_OF_BYTES_FREE: 1668
                     LOW_COUNT_USED: 0
                 CURRENT_COUNT_USED: 4
                    HIGH_COUNT_USED: 4
           LOW_NUMBER_OF_BYTES_USED: 0
       CURRENT_NUMBER_OF_BYTES_USED: 815
          HIGH_NUMBER_OF_BYTES_USED: 815
一致性中使用的内存

事务一致性保证的内存分配是consistent_members_that_must_prepare_transactionconsistent_transactionsconsistent_transactions_preparedconsistent_transactions_waitingconsistent_transactions_delayed_view_change事件值的总和。例如:

 mysql> SELECT * FROM (
                  SELECT
                    (CASE
                       WHEN EVENT_NAME = 'memory/group_rpl/consistent_members_that_must_prepare_transaction'
                       THEN 'memory/group_rpl/consistency'
                       WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions'
                       THEN 'memory/group_rpl/consistency'
                       WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions_prepared'
                       THEN 'memory/group_rpl/consistency'
                       WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions_waiting'
                       THEN 'memory/group_rpl/consistency'
                       WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions_delayed_view_change'
                       THEN 'memory/group_rpl/consistency'
                       ELSE 'memory_gr_rest'
                     END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
                    SUM(SUM_NUMBER_OF_BYTES_ALLOC),
                    SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
                    SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
                    SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
                    SUM(HIGH_NUMBER_OF_BYTES_USED)
                  FROM performance_schema.memory_summary_global_by_event_name
                  GROUP BY (CASE
                              WHEN EVENT_NAME = 'memory/group_rpl/consistent_members_that_must_prepare_transaction'
                              THEN 'memory/group_rpl/consistency'
                              WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions'
                              THEN 'memory/group_rpl/consistency'
                              WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions_prepared'
                              THEN 'memory/group_rpl/consistency'
                              WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions_waiting'
                              THEN 'memory/group_rpl/consistency'
                              WHEN EVENT_NAME = 'memory/group_rpl/consistent_transactions_delayed_view_change'
                              THEN 'memory/group_rpl/consistency'
                              ELSE 'memory_gr_rest'
                            END)
      ) f
      WHERE f.EVENT_NAME != 'memory_gr_rest'\G
      *************************** 1\. row ***************************
                        EVENT_NAME: memory/group_rpl/consistency
                       COUNT_ALLOC: 16
                        COUNT_FREE: 6
         SUM_NUMBER_OF_BYTES_ALLOC: 1464
          SUM_NUMBER_OF_BYTES_FREE: 528
                    LOW_COUNT_USED: 0
                CURRENT_COUNT_USED: 10
                   HIGH_COUNT_USED: 11
          LOW_NUMBER_OF_BYTES_USED: 0
      CURRENT_NUMBER_OF_BYTES_USED: 936
         HIGH_NUMBER_OF_BYTES_USED: 1024
交付消息服务中使用的内存

注意

此仪表适用于接收的数据,而不是发送的数据。

组复制交付消息服务的内存分配是message_service_received_messagemessage_service_queue事件值的总和。例如:

 mysql> SELECT * FROM (
                  SELECT
                    (CASE
                       WHEN EVENT_NAME = 'memory/group_rpl/message_service_received_message'
                       THEN 'memory/group_rpl/message_service'
                       WHEN EVENT_NAME = 'memory/group_rpl/message_service_queue'
                       THEN 'memory/group_rpl/message_service'
                       ELSE 'memory_gr_rest'
                     END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
                    SUM(SUM_NUMBER_OF_BYTES_ALLOC),
                    SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
                    SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
                    SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
                    SUM(HIGH_NUMBER_OF_BYTES_USED)
                  FROM performance_schema.memory_summary_global_by_event_name
                  GROUP BY (CASE
                              WHEN EVENT_NAME = 'memory/group_rpl/message_service_received_message'
                              THEN 'memory/group_rpl/message_service'
                              WHEN EVENT_NAME = 'memory/group_rpl/message_service_queue'
                              THEN 'memory/group_rpl/message_service'
                              ELSE 'memory_gr_rest'
                            END)
       ) f
       WHERE f.EVENT_NAME != 'memory_gr_rest'\G
       *************************** 1\. row ***************************
                         EVENT_NAME: memory/group_rpl/message_service
                        COUNT_ALLOC: 2
                         COUNT_FREE: 0
          SUM_NUMBER_OF_BYTES_ALLOC: 1048664
           SUM_NUMBER_OF_BYTES_FREE: 0
                     LOW_COUNT_USED: 0
                 CURRENT_COUNT_USED: 2
                    HIGH_COUNT_USED: 2
           LOW_NUMBER_OF_BYTES_USED: 0
       CURRENT_NUMBER_OF_BYTES_USED: 1048664
          HIGH_NUMBER_OF_BYTES_USED: 1048664
用于广播和接收事务的内存

用于广播和接收网络中事务的内存分配是wGcs_message_data::m_bufferGCS_XCom::xcom_cache事件值的总和。例如:

mysql> SELECT * FROM (
         SELECT
           (CASE
              WHEN EVENT_NAME = 'memory/group_rpl/Gcs_message_data::m_buffer'
              THEN 'memory/group_rpl/memory_gr'
              WHEN EVENT_NAME = 'memory/group_rpl/GCS_XCom::xcom_cache'
              THEN 'memory/group_rpl/memory_gr'
              ELSE 'memory_gr_rest'
            END) AS EVENT_NAME, SUM(COUNT_ALLOC), SUM(COUNT_FREE),
           SUM(SUM_NUMBER_OF_BYTES_ALLOC),
           SUM(SUM_NUMBER_OF_BYTES_FREE), SUM(LOW_COUNT_USED),
           SUM(CURRENT_COUNT_USED), SUM(HIGH_COUNT_USED),
           SUM(LOW_NUMBER_OF_BYTES_USED), SUM(CURRENT_NUMBER_OF_BYTES_USED),
           SUM(HIGH_NUMBER_OF_BYTES_USED)
         FROM performance_schema.memory_summary_global_by_event_name
         GROUP BY (CASE
                     WHEN EVENT_NAME = 'memory/group_rpl/Gcs_message_data::m_buffer'
                     THEN 'memory/group_rpl/memory_gr'
                     WHEN EVENT_NAME = 'memory/group_rpl/GCS_XCom::xcom_cache'
                     THEN 'memory/group_rpl/memory_gr'
                     ELSE 'memory_gr_rest'
                   END)
       ) f
       WHERE f.EVENT_NAME != 'memory_gr_rest'\G
       *************************** 1\. row ***************************
                              EVENT_NAME: memory/group_rpl/memory_gr
                        SUM(COUNT_ALLOC): 73
                         SUM(COUNT_FREE): 20
          SUM(SUM_NUMBER_OF_BYTES_ALLOC): 1070845
           SUM(SUM_NUMBER_OF_BYTES_FREE): 5670
                     SUM(LOW_COUNT_USED): 0
                 SUM(CURRENT_COUNT_USED): 53
                    SUM(HIGH_COUNT_USED): 56
           SUM(LOW_NUMBER_OF_BYTES_USED): 0
       SUM(CURRENT_NUMBER_OF_BYTES_USED): 1065175
          SUM(HIGH_NUMBER_OF_BYTES_USED): 1065175

20.8 升级群组复制

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-upgrade.html

20.8.1 在群组中合并不同成员版本

20.8.2 群组复制离线升级

20.8.3 群组复制在线升级

本节解释了如何升级群组复制设置。升级群组成员的基本过程与升级独立实例的过程相同,请参阅 Chapter 3, Upgrading MySQL了解实际的升级过程和可用的类型。在原地升级和逻辑升级之间的选择取决于群组中存储的数据量。通常,原地升级更快,因此建议使用。您还应该参考 Section 19.5.3, “Upgrading a Replication Topology”。

在升级在线群组的过程中,为了最大化可用性,您可能需要在同一时间运行具有不同 MySQL 服务器版本的成员。群组复制包括兼容性策略,使您能够在升级过程中安全地将运行不同 MySQL 版本的成员合并到同一群组中。根据您的群组,这些策略的影响可能会影响您应该升级群组成员的顺序。有关详细信息,请参见 Section 20.8.1, “Combining Different Member Versions in a Group”。

如果您的群组可以完全脱机,请参见 Section 20.8.2, “群组复制离线升级”。如果您的群组需要保持在线,这在生产部署中很常见,请参见 Section 20.8.3, “群组复制在线升级”,了解升级群组的不同方法以最小化停机时间。

20.8.1 在组中组合不同的成员版本

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-online-upgrade-combining-versions.html

20.8.1.1 升级期间的成员版本

20.8.1.2 组复制通信协议版本

组复制的版本与捆绑有 Group Replication 插件的 MySQL 服务器版本相对应。例如,如果一个成员运行 MySQL 5.7.26,则 Group Replication 插件的版本就是这个版本。要检查组成员上的 MySQL 服务器版本,请发出:

SELECT MEMBER_HOST,MEMBER_PORT,MEMBER_VERSION FROM performance_schema.replication_group_members;
+-------------+-------------+----------------+
| member_host | member_port | member_version |
+-------------+-------------+----------------+
| example.com |	   3306     |   8.0.13	     |
+-------------+-------------+----------------+

有关理解 MySQL 服务器版本和选择版本的指导,请参见 Section 2.1.2,“选择要安装的 MySQL 版本和发行版”。

为了获得最佳兼容性和性能,组中的所有成员应该运行相同版本的 MySQL 服务器,因此也应该运行相同版本的组复制。然而,在在线升级组的过程中,为了最大化可用性,您可能需要同时运行具有不同 MySQL 服务器版本的成员。根据 MySQL 版本之间的更改,您可能会在这种情况下遇到不兼容性。例如,如果在主要版本之间已弃用某个功能,则将版本组合到组中可能导致依赖于已弃用功能的成员失败。相反,如果在组中有运行较新 MySQL 版本的读写成员时向运行较旧 MySQL 版本的成员写入数据,可能会导致缺少较新版本引入的功能的成员出现问题。

为了防止这些问题,组复制包括兼容性策略,使您能够安全地将运行不同 MySQL 版本的成员组合到同一组中。成员应用这些策略来决定是否正常加入组,或以只读模式加入,或不加入组,具体取决于哪种选择能够确保加入成员和现有组成员的安全运行。在升级场景中,每个服务器必须离开组,进行升级,然后使用新的服务器版本重新加入组。此时,成员将应用其新服务器版本的策略,这可能已经与其最初加入组时应用的策略不同。

作为管理员,你可以通过配置服务器并发出 START GROUP_REPLICATION 语句,指示任何服务器尝试加入任何组。加入组或不加入组,或以只读模式加入组的决定由加入成员自己在尝试将其添加到组后进行,并由其自行实施。加入成员接收当前组成员的 MySQL 服务器版本信息,评估自己与这些成员的兼容性,并应用其自己 MySQL 服务器版本中使用的策略(而不是现有成员使用的策略)来决定是否兼容。

加入组时,加入成员应用的兼容性策略如下:

  • 如果成员运行的 MySQL 服务器版本低于现有组成员运行的最低版本,则该成员不加入组。

  • 如果成员运行的 MySQL 服务器版本与现有组成员运行的最低版本相同,则该成员正常加入组。

  • 如果成员运行的 MySQL 服务器版本高于现有组成员运行的最低版本,则该成员加入组但保持只读模式。这种行为仅在组以多主模式运行时才有区别,因为在以单主模式运行的组中,新添加的成员默认始终为只读模式。

运行 MySQL 8.0.17 或更高版本的成员在检查兼容性时考虑发布的补丁版本。运行 MySQL 8.0.16 或更低版本,或 MySQL 5.7 的成员只考虑主要版本。例如,如果你有一个所有成员都运行 MySQL 版本 8.0.13 的组:

  • 运行 MySQL 版本 5.7 的成员无法加入。

  • 运行 MySQL 8.0.16 的成员正常加入(因为它考虑主要版本)。

  • 运行 MySQL 8.0.17 的成员加入但保持只读模式(因为它考虑了补丁版本)。

请注意,运行 MySQL 5.7.27 之前版本的加入成员会检查所有组成员,以确定自己的 MySQL 服务器主要版本是否较低。因此,对于任何成员运行 MySQL 8.0 版本的组,它们将无法通过此检查,即使该组已经有其他运行 MySQL 5.7 的成员。从 MySQL 5.7.27 开始,加入成员只会检查运行最低主要版本的组成员,因此它们可以加入一个混合版本组,其中存在其他 MySQL 5.7 服务器。

在一个多主模式组中,成员使用不同的 MySQL Server 版本,Group Replication 会自动管理运行 MySQL 8.0.17 或更高版本的成员的读写和只读状态。如果一个成员离开组,那些运行当前最低版本的成员会自动设置为读写模式。当你将原本以单主模式运行的组改为多主模式时,使用group_replication_switch_to_multi_primary_mode()函数,Group Replication 会自动将成员设置为正确的模式。如果某些成员运行的 MySQL 服务器版本高于组中最低版本,那么它们会自动被设置为只读模式,而运行最低版本的成员会被设置为读写模式。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-compatibility-upgrade.html

20.8.1.1 升级过程中的成员版本

在在线升级过程中,如果组处于单主模式,则所有当前未脱机升级的服务器将像以前一样运行。每当需要时,组会选举新的主服务器,遵循第 20.1.3.1 节“单主模式”中描述的选举策略。请注意,如果您要求主服务器在整个过程中保持不变(除非它本身正在升级),则必须首先将所有次要服务器升级到高于或等于目标主服务器版本的版本,然后最后升级主服务器。主服务器不能保持为主服务器,除非它正在运行组中最低的 MySQL 服务器版本。主服务器升级后,您可以使用group_replication_set_as_primary()函数重新任命它为主服务器。

如果组处于多主模式,则在升级过程中可用于执行写操作的在线成员较少,因为升级后的成员在升级后以只读模式加入。从 MySQL 8.0.17 开始,这适用于补丁版本之间的升级,对于较低版本,这仅适用于主要版本之间的升级。当所有成员都升级到相同版本时,从 MySQL 8.0.17 开始,它们都会自动切换回读写模式。对于早期版本,您必须在每个应在升级后充当主服务器的成员上手动将super_read_only设置为OFF

为了处理问题情况,例如如果您必须回滚升级或在紧急情况下增加组的额外容量,可以允许成员加入在线组,尽管其运行的 MySQL 服务器版本低于其他组成员使用的最低版本。在这种情况下,可以使用 Group Replication 系统变量group_replication_allow_local_lower_version_join来覆盖正常的兼容性策略。

重要提示

group_replication_allow_local_lower_version_join设置为ON使新成员与组兼容;这样做允许其加入组,而没有任何防范措施来防止现有成员的不兼容行为。因此,这必须仅在特定情况下小心使用,并且您必须采取额外预防措施,以避免新成员由于正常组活动而失败。有关此变量的更多信息,请参阅其描述。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-compatibility-communication.html

20.8.1.2 Group Replication 通信协议版本

复制组使用的 Group Replication 通信协议版本可能与成员的 MySQL Server 版本不同。要检查组的通信协议版本,请在任何成员上发出以下语句:

SELECT group_replication_get_communication_protocol();

返回值显示了可以加入此组并使用组通信协议的最旧 MySQL Server 版本。从 MySQL 5.7.14 版本开始允许消息压缩,而从 MySQL 8.0.16 版本开始还允许消息分段。请注意,group_replication_get_communication_protocol() 函数返回组支持的最低 MySQL 版本,这可能与传递给 group_replication_set_communication_protocol() 函数的版本号不同,并且可能与在使用该函数的成员上安装的 MySQL Server 版本不同。

当您将复制组的所有成员升级到新的 MySQL Server 版本时,Group Replication 通信协议版本不会自动升级,以防仍然需要允许早期版本的成员加入。如果您不需要支持旧版本成员,并希望允许升级后的成员使用任何新增的通信功能,在升级后使用 group_replication_set_communication_protocol() 函数升级通信协议,指定您已将成员升级到的新 MySQL Server 版本。有关更多信息,请参见 Section 20.5.1.4, “Setting a Group's Communication Protocol Version”。

20.8.2 Group Replication 离线升级

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-offline-upgrade.html

要执行 Group Replication 组的离线升级,您需要将每个成员从组中移除,对成员进行升级,然后像往常一样重新启动组。在多主组中,您可以以任何顺序关闭成员。在单主组中,首先关闭每个次要成员,然后最后关闭主要成员。参见第 20.8.3.2 节,“升级 Group Replication 成员”了解如何从组中移除成员并关闭 MySQL。

一旦组离线,升级所有成员。参见第三章,升级 MySQL了解如何执行升级。当所有成员都升级完毕后,重新启动成员。

如果在组离线时升级所有复制组成员,然后重新启动组,成员将使用新版本的 Group Replication 通信协议版本加入,因此该版本将成为组的通信协议版本。如果您有要求允许较早版本的成员加入,您可以使用group_replication_set_communication_protocol()函数降级通信协议版本,指定具有最旧安装服务器版本的潜在组成员的 MySQL 服务器版本。

20.8.3 集群复制在线升级

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-online-upgrade.html

20.8.3.1 在线升级考虑事项

20.8.3.2 升级集群复制成员

20.8.3.3 集群复制在线升级方法

20.8.3.4 使用mysqlbackup进行集群复制升级

当您有一个正在运行的集群需要升级,但您需要保持集群在线以提供应用程序服务时,您需要考虑升级的方法。本节描述了在线升级涉及的不同元素,以及如何升级您的集群的各种方法。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-online-upgrade-considerations.html

20.8.3.1 在线升级注意事项

在升级在线组时,您应考虑以下几点:

  • 无论您如何升级您的组,重要的是在他们准备重新加入组之前禁用对组成员的任何写入。

  • 当成员停止时,super_read_only 变量会自动设置为打开,但此更改不会持久保存。

  • 当 MySQL 5.7.22 或 MySQL 8.0.11 尝试加入运行 MySQL 5.7.21 或更低版本的组时,它无法加入该组,因为 MySQL 5.7.21 不会发送其 lower_case_table_names 的值。

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-upgrading-member.html

20.8.3.2 升级组复制成员

本节解释了升级组成员所需的步骤。此过程是第 20.8.3.3 节“组复制在线升级方法”描述的方法的一部分。升级组成员的过程对所有方法都是通用的,并首先进行解释。加入升级成员的方式可能取决于您正在遵循的方法,以及诸如组是在单主还是多主模式下运行等其他因素。您如何升级服务器实例,无论是使用就地升级还是预置方法,都不会影响此处描述的方法。

升级成员的过程包括将其从组中移除,按照您选择的升级成员的方法进行升级,然后将升级后的成员重新加入组。在单主组中升级成员的推荐顺序是先升级所有次要成员,然后最后再升级主要成员。如果在次要成员之前升级主要成员,则会选择使用旧版 MySQL 版本的新主要成员,但这一步是不必要的。

要升级组的成员:

  • 连接客户端到组成员并发出STOP GROUP_REPLICATION。在继续之前,请通过监视replication_group_members表确保成员的状态为OFFLINE

  • 禁用自动启动组复制,以便您可以安全地在升级后连接到成员并进行配置,而不会在设置group_replication_start_on_boot=0后重新加入组。

    重要

    如果升级的成员设置了group_replication_start_on_boot=1,那么在你执行 MySQL 升级过程之前,它可能会重新加入组,并可能导致问题。例如,如果升级失败并且服务器再次重启,那么可能会尝试加入组的是一个可能损坏的服务器。

  • 停止成员,例如使用mysqladmin shutdownSHUTDOWN语句。组中的其他成员继续运行。

  • 使用就地或配置方法升级成员。有关详细信息,请参见第三章,升级 MySQL。在重新启动升级后的成员时,因为group_replication_start_on_boot设置为 0,Group Replication 不会在实例上启动,因此它不会重新加入组。

  • 一旦在成员上执行了 MySQL 升级过程,必须将group_replication_start_on_boot设置为 1,以确保在重新启动后正确启动 Group Replication。重新启动成员。

  • 连接到升级后的成员并发出START GROUP_REPLICATION。这将重新加入成员到组中。升级服务器上已经存在 Group Replication 元数据,因此通常不需要重新配置 Group Replication。服务器必须赶上在其离线时组处理的任何事务。一旦赶上组,它就成为组的在线成员。

    注意

    升级服务器所需的时间越长,该成员离线的时间就越长,因此在重新添加到组中时,服务器需要花费更多时间来赶上。

当升级后的成员加入任何运行较早 MySQL 服务器版本的组时,升级后的成员会以super_read_only=on加入。这确保在所有成员都运行新版本之前,不会向升级后的成员进行写入。在多主模式组中,当升级成功完成并且组准备好处理事务时,打算作为可写主节点的成员必须设置为读写模式。从 MySQL 8.0.17 开始,当组的所有成员都升级到相同版本时,它们都会自动切换回读写模式。对于早期版本,您必须手动将每个成员设置为读写模式。连接到每个成员并发出:

SET GLOBAL super_read_only=OFF;

原文:dev.mysql.com/doc/refman/8.0/en/group-replication-online-upgrade-methods.html

20.8.3.3 Group Replication Online Upgrade Methods

选择以下升级 Group Replication 组的方法之一:

滚动式组内升级

只要运行较新版本的服务器不会在仍有较旧版本的服务器的情况下向组生成工作负载,此方法就受支持。换句话说,只有运行较新版本的服务器可以作为辅助服务器加入组。在此方法中,只有一个组,每个服务器实例都会从组中移除,升级,然后重新加入组。

此方法非常适用于单主组。当组以单主模式运行时,如果您要求主服务器在整个过程中保持不变(除非正在升级自身),则应将其作为最后一个升级的成员。主服务器必须在组中运行最低版本的 MySQL 服务器版本才能保持为主服务器。主服务器升级后,您可以使用group_replication_set_as_primary()函数将其重新指定为主服务器。如果您不在意哪个成员是主服务器,那么成员可以以任何顺序进行升级。组在必要时从运行最低 MySQL 服务器版本的成员中选举新的主服务器,遵循第 20.1.3.1 节,“单主模式”中描述的选举策略。

对于以多主模式运行的组,在组内滚动升级期间,主服务器数量会减少,导致写入可用性降低。这是因为如果成员在组运行时加入组,而其运行的 MySQL 服务器版本高于现有组成员运行的最低版本,则它会自动保持为只读模式(super_read_only=ON)。请注意,运行 MySQL 8.0.17 或更高版本的成员在检查时会考虑发布的补丁版本,但运行 MySQL 8.0.16 或更低版本,或 MySQL 5.7 的成员只会考虑主要版本。当所有成员升级到相同版本后,从 MySQL 8.0.17 开始,它们会自动恢复为读写模式。对于早期版本,您必须在每个成员上手动设置super_read_only=OFF,以便在升级后作为主服务器运行。

有关组中版本兼容性的完整信息以及这如何影响升级过程中组的行为,请参阅第 20.8.1 节,“组中不同成员版本的组合”。

滚动式迁移升级

在这种方法中,您将从组中移除成员,升级它们,然后使用升级后的成员创建第二组。对于在多主模式下运行的组,在此过程中主节点的数量会减少,导致写入可用性降低。这不会影响在单主模式下运行的组。

因为在升级成员时运行较旧版本的组在线,所以需要运行较新版本的组赶上在升级成员时执行的任何事务。因此,新组中的一个服务器被配置为较旧组的主节点的副本。这确保新组赶上较旧组。由于此方法依赖于用于将数据从一个组复制到另一个组的异步复制通道,因此它在异步源-副本复制的相同假设和要求下受支持,参见 Chapter 19, 复制。对于在单主模式下运行的组,向旧组的异步复制连接必须发送数据到新组的主节点,对于多主组,异步复制通道可以连接到任何主节点。

过程如下:

  • 逐个从运行较旧服务器版本的原始组中移除成员,参见 Section 20.8.3.2, “升级组复制成员”

  • 升级运行在成员上的服务器版本,参见 Chapter 3, 升级 MySQL。您可以选择进行就地升级或预置升级的方法。

  • 创建一个具有升级成员的新组,参见 Chapter 20, 组复制。在这种情况下,您需要在每个成员上配置一个新组名称(因为旧组仍在运行并使用旧名称),引导一个初始升级成员,然后添加其余的升级成员。

  • 在旧组和新组之间建立一个异步复制通道,参见 Section 19.1.3.4, “使用 GTIDs 设置复制”。将较旧的主节点配置为异步复制源服务器,将新组成员配置为基于 GTID 的副本。

在将应用程序重定向到新组之前,您必须确保新组具有合适数量的成员,例如使组能够处理成员的故障。执行SELECT * FROM performance_schema.replication_group_members并比较初始组大小和新组大小。等到所有旧组的数据传播到新组,然后删除异步复制连接并升级任何缺失的成员。

滚动复制升级

在这种方法中,您创建一个由运行较新版本的成员组成的第二组,并将旧组缺失的数据复制到较新组。这假定您有足够的服务器同时运行两个组。由于在此过程中主服务器的数量减少,对于运行在多主模式下的组来说,写入可用性不会减少。这使得滚动复制升级非常适合在多主模式下运行的组。这不会影响在单主模式下运行的组。

因为在为新组的成员提供资源时,运行旧版本的组在线,您需要确保运行较新版本的组赶上在为成员提供资源时执行的任何事务。因此,新组中的一个服务器被配置为旧组的主服务器的副本。这确保新组赶上旧组。由于此方法依赖于用于将数据从一个组复制到另一个组的异步复制通道,因此它在相同的异步源-副本复制的假设和要求下受支持,请参阅第十九章,复制。对于在单主模式下运行的组,异步复制连接到旧组必须将数据发送到新组的主服务器,对于多主组,异步复制通道可以连接到任何主服务器。

过程是:

  • 部署适当数量的成员,以便运行较新版本的组可以处理成员的故障

  • 对组中的一个成员进行现有数据的备份

  • 使用来自旧成员的备份为新组的成员提供资源,请参阅第 20.8.3.4 节,“使用mysqlbackup进行组复制升级”中的一种方法。

    注意

    您必须将备份还原到与备份所在的 MySQL 版本相同的版本,然后执行就地升级。有关说明,请参阅第三章,升级 MySQL

  • 创建一个包含升级成员的新组,请参阅第二十章,组复制。在这种情况下,您需要在每个成员上配置一个新的组名(因为旧组仍在运行并使用旧名称),引导一个初始升级成员,然后添加其余的升级成员。

  • 在旧组和新组之间建立一个异步复制通道,请参阅第 19.1.3.4 节,“使用 GTIDs 设置复制”。将较旧的主服务器配置为异步复制源服务器,将新组成员配置为基于 GTID 的副本。

一旦新组中缺失的持续数据量足够小,可以快速传输,您必须将写操作重定向到新组。等到所有旧组的数据传播到新组,然后断开异步复制连接。

posted @ 2024-06-23 00:40  绝不原创的飞龙  阅读(6)  评论(0编辑  收藏  举报