前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL8 中文参考(八十)

MySQL8 中文参考(八十)

作者头像
ApacheCN_飞龙
发布2024-06-26 19:15:08
750
发布2024-06-26 19:15:08
举报
文章被收录于专栏:信数据得永生信数据得永生

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

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

19.4.10.2 配置半同步复制

当您为半同步复制安装源和复制品插件时(参见 Section 19.4.10.1,“安装半同步复制”),系统变量变得可用以控制插件行为。

要检查半同步复制状态变量的当前值,请使用 SHOW VARIABLES

代码语言:javascript
复制
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';

从 MySQL 8.0.26 开始,提供了源和复制品插件的新版本,这些版本在系统变量和状态变量中将“master”和“slave”替换为“source”和“replica”。如果安装新的 rpl_semi_sync_sourcerpl_semi_sync_replica 插件,则新的系统变量和状态变量可用,但旧的则不可用。如果安装旧的 rpl_semi_sync_masterrpl_semi_sync_slave 插件,则旧的系统变量和状态变量可用,但新的则不可用。在一个实例中不能同时安装相关插件的新旧版本。

所有 rpl_semi_sync_*xxx* 系统变量在 Section 19.1.6.2,“复制源选项和变量”和 Section 19.1.6.3,“复制品服务器选项和变量”中有描述。一些关键的系统变量包括:

rpl_semi_sync_source_enabledrpl_semi_sync_master_enabled

控制源服务器上是否启用半同步复制。要启用或禁用插件,请将此变量分别设置为 1 或 0。默认值为 0(关闭)。

rpl_semi_sync_replica_enabledrpl_semi_sync_slave_enabled

控制复制品上是否启用半同步复制。

rpl_semi_sync_source_timeoutrpl_semi_sync_master_timeout

以毫秒为单位的值,控制源在提交时等待来自复制品的确认的超时时间,超时后将回滚到异步复制。默认值为 10000(10 秒)。

rpl_semi_sync_source_wait_for_replica_countrpl_semi_sync_master_wait_for_slave_count

控制源在返回会话之前必须接收的每个事务的副本确认数。默认值为 1,意味着源只等待一个副本确认接收事务事件。

rpl_semi_sync_source_wait_pointrpl_semi_sync_master_wait_point 系统变量控制半同步源服务器在返回事务提交状态给客户端之前等待副本确认事务接收的时间点。这些值是允许的:

  • AFTER_SYNC(默认):源将每个事务写入其二进制日志和副本,并将二进制日志同步到磁盘。源在同步后等待副本确认事务接收。在接收到确认后,源将事务提交到存储引擎并返回结果给客户端,然后客户端可以继续。
  • AFTER_COMMIT:源将每个事务写入其二进制日志和副本,同步二进制日志,并提交事务到存储引擎。源在提交后等待副本确认事务接收。在接收到确认后,源返回结果给客户端,然后客户端可以继续。

这些设置的复制特性如下所示:

  • 使用 AFTER_SYNC,所有客户端在同一时间看到已提交的事务,即在副本确认并在源上提交到存储引擎之后。因此,所有客户端在源上看到相同的数据。 在源故障的情况下,所有在源上提交的事务已被复制到副本(保存到其中继日志)。源的意外退出并故障转移到副本是无损的,因为副本是最新的。如上所述,在故障转移后不应再重用源。
  • 使用 AFTER_COMMIT,发起事务的客户端只有在服务器提交到存储引擎并接收到副本确认后才会收到返回状态。在提交后和副本确认前,其他客户端可能在提交客户端之前看到已提交的事务。 如果出现问题导致副本未处理事务,那么在源意外退出并故障转移到副本的情况下,这些客户端可能会看到相对于在源上看到的数据有所丢失。

从 MySQL 8.0.23 开始,您可以通过启用系统变量replication_sender_observe_commit_onlyreplication_optimize_for_static_plugin_config来提高半同步复制的性能,前者限制回调,后者添加共享锁并避免不必要的锁获取。这些设置在副本数量增加时非常有帮助,因为锁争用可能会降低性能。半同步复制源服务器还可以通过启用这些系统变量获得性能优势,因为它们使用与副本相同的锁定机制。

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

19.4.10.3 半同步复制监控

半同步复制的插件公开了许多状态变量,使您能够监视其操作。要检查状态变量的当前值,请使用 SHOW STATUS

代码语言:javascript
复制
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';

从 MySQL 8.0.26 开始,提供了新版本的源和副本插件,这些插件在系统变量和状态变量中用“source”和“replica”替换了“master”和“slave”这些术语。如果安装了新的 rpl_semi_sync_sourcerpl_semi_sync_replica 插件,则新的系统变量和状态变量可用,而旧的则不可用。如果安装了旧的 rpl_semi_sync_masterrpl_semi_sync_slave 插件,则旧的系统变量和状态变量可用,而新的则不可用。在一个实例中不能同时安装相关插件的新旧版本。

所有 Rpl_semi_sync_*xxx* 状态变量在 第 7.1.10 节,“服务器状态变量” 中有描述。一些示例包括:

  • Rpl_semi_sync_source_clientsRpl_semi_sync_master_clients 连接到源服务器的半同步副本数量。
  • Rpl_semi_sync_source_statusRpl_semi_sync_master_status 半同步复制当前是否在源服务器上运行。如果插件已启用且提交确认尚未发生,则值为 1。如果插件未启用或源由于提交确认超时而回退到异步复制,则值为 0。
  • Rpl_semi_sync_source_no_txRpl_semi_sync_master_no_tx 未被副本成功确认的提交数量。
  • Rpl_semi_sync_source_yes_txRpl_semi_sync_master_yes_tx 被副本成功确认的提交数量。
  • Rpl_semi_sync_replica_statusRpl_semi_sync_slave_status 半同步复制当前是否在副本上运行。如果插件已启用且复制 I/O(接收器)线程正在运行,则为 1,否则为 0。

当源端由于提交阻塞超时或副本追赶而在异步或半同步复制之间切换时,它会适当地设置Rpl_semi_sync_source_statusRpl_semi_sync_master_status状态变量的值。源端从半同步自动回退到异步复制意味着即使半同步复制实际上当前不可用,rpl_semi_sync_source_enabledrpl_semi_sync_master_enabled系统变量在源端可能仍然具有值 1。您可以监视Rpl_semi_sync_source_statusRpl_semi_sync_master_status状态变量来确定源端当前是在使用异步还是半同步复制。

19.4.11 延迟复制

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

MySQL 支持延迟复制,使得副本服务器故意比源服务器晚至少指定的时间执行事务。本节描述了如何在副本上配置复制延迟以及如何监视复制延迟。

在 MySQL 8.0 中,延迟复制的方法取决于两个时间戳,immediate_commit_timestamporiginal_commit_timestamp(参见 Replication Delay Timestamps)。如果复制拓扑中的所有服务器都运行 MySQL 8.0 或更高版本,则使用这些时间戳来测量延迟复制。如果即时源或副本中有任何一个不使用这些时间戳,则使用 MySQL 5.7 中的延迟复制实现(参见 Delayed Replication)。本节描述了所有使用这些时间戳的服务器之间的延迟复制。

默认复制延迟为 0 秒。使用CHANGE REPLICATION SOURCE TO SOURCE_DELAY=*N*语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO MASTER_DELAY=*N*语句(MySQL 8.0.23 之前)将延迟设置为*N秒。从源接收的事务直到比其在即时源上提交的时间晚至少N*秒才执行。延迟是按事务发生的(而不是像以前的 MySQL 版本中那样按事件发生),实际延迟仅对gtid_log_eventanonymous_gtid_log_event施加。事务中的其他事件总是在这些事件之后立即执行,而不会对它们施加任何等待时间。

注意

START REPLICASTOP REPLICA立即生效并忽略任何延迟。RESET REPLICA将延迟重置为 0。

replication_applier_configuration性能模式表包含DESIRED_DELAY列,显示使用SOURCE_DELAY | MASTER_DELAY选项配置的延迟。replication_applier_status性能模式表包含REMAINING_DELAY列,显示剩余的延迟秒数。

延迟复制可用于几个目的:

  • 用于防止源上用户错误。通过延迟,您可以将延迟副本回滚到错误发生之前的时间。
  • 为了测试系统在出现延迟时的行为。例如,在一个应用程序中,延迟可能是由于副本上的大量负载而引起的。然而,很难生成这种负载水平。延迟复制可以模拟延迟,而无需模拟负载。它还可以用于调试与滞后副本相关的条件。
  • 为了查看数据库在过去的样子,而无需重新加载备份。例如,通过配置一个延迟一周的副本,如果您需要查看数据库在最近几天开发之前的样子,可以检查延迟副本。
复制延迟时间戳

MySQL 8.0 提供了一种新的方法来测量复制拓扑中的延迟(也称为复制滞后),该方法依赖于写入二进制日志的每个事务(而不是每个事件)关联的 GTID 的以下时间戳。

  • original_commit_timestamp: 事务被写入(提交)到原始来源二进制日志时距离时代的微秒数。
  • immediate_commit_timestamp: 事务被写入(提交)到直接来源二进制日志时距离时代的微秒数。

mysqlbinlog的输出以两种格式显示这些时间戳,即从时代开始的微秒数和基于用户定义时区的TIMESTAMP格式,以便更易读。例如:

代码语言:javascript
复制
#170404 10:48:05 server id 1  end_log_pos 233 CRC32 0x016ce647     GTID    last_committed=0
\ sequence_number=1    original_committed_timestamp=1491299285661130    immediate_commit_timestamp=1491299285843771
# original_commit_timestamp=1491299285661130 (2017-04-04 10:48:05.661130 WEST)
# immediate_commit_timestamp=1491299285843771 (2017-04-04 10:48:05.843771 WEST)
 /*!80001 SET @@SESSION.original_commit_timestamp=1491299285661130*//*!*/;
   SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1'/*!*/;
# at 233

通常情况下,事务应用到的所有副本上的original_commit_timestamp始终相同。在源-副本复制中,事务在(原始)源二进制日志中的original_commit_timestamp始终与其immediate_commit_timestamp相同。在副本的中继日志中,事务的original_commit_timestampimmediate_commit_timestamp与源二进制日志中的相同;而在其自己的二进制日志中,事务的immediate_commit_timestamp对应于副本提交事务的时间。

在群组复制设置中,当原始来源是群组的成员时,original_commit_timestamp在事务准备提交时生成。换句话说,当它在原始来源上执行完毕并且其写入集准备发送到群组的所有成员进行认证时。当原始来源是群组外的服务器时,original_commit_timestamp被保留。特定事务的相同original_commit_timestamp被复制到群组中的所有服务器,以及从成员复制的群组外的任何副本。从 MySQL 8.0.26 开始,事务的每个接收者还使用immediate_commit_timestamp在其二进制日志中存储本地提交时间。

视图更改事件,这是组复制独有的特殊情况。包含这些事件的交易由每个组成员生成,但共享相同的 GTID(因此,它们不是首先在源中执行,然后被复制到组中,而是组的所有成员执行并应用相同的交易)。在 MySQL 8.0.26 之前,这些交易的original_commit_timestamp设置为零,并且在可查看的输出中以这种方式显示。从 MySQL 8.0.26 开始,为了提高可观察性,组成员为与视图更改事件相关的交易设置本地时间戳值。

监视复制延迟

在以前的 MySQL 版本中监视复制延迟(滞后)最常见的方法之一是依赖于SHOW REPLICA STATUS输出中的Seconds_Behind_Master字段。然而,在使用比传统源-副本设置更复杂的复制拓扑时,如组复制时,此度量标准并不适用。在 MySQL 8 中添加immediate_commit_timestamporiginal_commit_timestamp提供了关于复制延迟的更精细信息。在支持这些时间戳的拓扑中监视复制延迟的推荐方法是使用以下性能模式表。

  • replication_connection_status:与源的连接的当前状态,提供连接线程排队到中继日志的最后一个和当前交易的信息。
  • replication_applier_status_by_coordinator:仅在使用多线程副本时显示协调器线程的当前状态,提供协调器线程缓冲到工作线程队列的最后一个交易的信息,以及它当前正在缓冲的交易。
  • replication_applier_status_by_worker:应用来自源的交易的线程(们)的当前状态,提供由复制 SQL 线程应用的交易的信息,或者在使用多线程副本时,每个工作线程应用的交易的信息。

使用这些表,您可以监视对应线程处理的最后一个交易和该线程当前正在处理的交易的信息。这些信息包括:

  • 一个交易的 GTID
  • 从副本的中继日志中检索的交易的original_commit_timestampimmediate_commit_timestamp
  • 线程开始处理交易的时间
  • 对于最后处理的交易,线程完成处理的时间

除了性能模式表之外,SHOW REPLICA STATUS的输出还有三个字段显示:

  • SQL_Delay: 一个非负整数,表示使用CHANGE REPLICATION SOURCE TO SOURCE_DELAY=*N*(从 MySQL 8.0.23 开始)或CHANGE MASTER TO MASTER_DELAY=N(在 MySQL 8.0.23 之前)配置的复制延迟,以秒为单位。
  • SQL_Remaining_Delay: 当Replica_SQL_Running_StateWaiting until MASTER_DELAY seconds after master executed event时,此字段包含一个整数,表示延迟剩余的秒数。在其他时候,此字段为NULL
  • Replica_SQL_Running_State: 表示 SQL 线程状态的字符串(类似于Replica_IO_State)。该值与由SHOW PROCESSLIST显示的 SQL 线程的State值相同。

当复制 SQL 线程在执行事件之前等待延迟时间时,SHOW PROCESSLIST将其State值显示为Waiting until MASTER_DELAY seconds after master executed event

19.5 复制笔记和技巧

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

19.5.1 复制功能和问题

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

19.5.3 升级复制拓扑结构

19.5.4 复制故障排除

19.5.5 如何报告复制错误或问题

19.5.1 复制功能和问题

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

19.5.1.1 复制和 AUTO_INCREMENT

19.5.1.2 复制和 BLACKHOLE 表

19.5.1.3 复制和字符集

19.5.1.4 复制和 CHECKSUM TABLE

19.5.1.5 创建服务器,修改服务器和删除服务器的复制

19.5.1.6 CREATE … IF NOT EXISTS 语句的复制

19.5.1.7 复制 CREATE TABLE … SELECT 语句

19.5.1.8 CURRENT_USER()的复制

19.5.1.9 源和副本上的不同表定义的复制

19.5.1.10 复制和 DIRECTORY 表选项

19.5.1.11 复制 DROP … IF EXISTS 语句

19.5.1.12 复制和浮点值

19.5.1.13 复制和 FLUSH

19.5.1.14 复制和系统函数

19.5.1.15 复制和分数秒支持

19.5.1.16 调用功能的复制

19.5.1.17 复制 JSON 文档

19.5.1.18 复制和 LIMIT

19.5.1.19 复制和 LOAD DATA

19.5.1.20 复制和 max_allowed_packet

19.5.1.21 复制和 MEMORY 表

19.5.1.22 复制 mysql 系统模式

19.5.1.23 复制和查询优化器

19.5.1.24 复制和分区

19.5.1.25 复制和 REPAIR TABLE

19.5.1.26 复制和保留字

19.5.1.27 复制和行搜索

19.5.1.28 复制和源或副本的关闭

19.5.1.29 复制过程中的副本错误

19.5.1.30 复制和服务器 SQL 模式

19.5.1.31 复制和临时表

19.5.1.32 复制重试和超时

19.5.1.33 复制和时区

19.5.1.34 复制和事务不一致性

19.5.1.35 复制和事务

19.5.1.36 复制和触发器

19.5.1.37 复制和 TRUNCATE TABLE

19.5.1.38 复制和用户名长度

19.5.1.39 复制和变量

19.5.1.40 复制和视图

以下各节提供了关于 MySQL 复制中支持和不支持的内容,以及在复制某些语句时可能发生的特定问题和情况的信息。

基于语句的复制取决于源和副本之间在 SQL 级别的兼容性。换句话说,成功的基于语句的复制要求源服务器和副本服务器都支持使用的任何 SQL 特性。如果您在源服务器上使用了仅在当前版本的 MySQL 中可用的功能,则无法复制到使用较早版本的 MySQL 的副本。这种不兼容性也可能发生在版本系列内以及版本之间。

如果您计划在 MySQL 8.0 和之前的 MySQL 版本系列之间使用基于语句的复制,建议查阅MySQL 参考手册对应早期版本系列的版本,以获取有关该系列复制特性的信息。

使用 MySQL 的基于语句的复制时,可能会出现复制存储过程或触发器的问题。您可以通过改用 MySQL 的基于行的复制来避免这些问题。有关问题的详细列表,请参阅第 27.7 节,“存储程序二进制日志记录”。有关基于行的日志记录和基于行的复制的更多信息,请参阅第 7.4.4.1 节,“二进制日志格式”,以及第 19.2.1 节,“复制格式”。

对于与InnoDB复制相关的其他信息,请参阅第 17.19 节,“InnoDB 和 MySQL 复制”。有关与 NDB Cluster 复制相关的信息,请参阅第 25.7 节,“NDB Cluster 复制”。

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

19.5.1.1 复制和 AUTO_INCREMENT

基于语句的复制AUTO_INCREMENTLAST_INSERT_ID()TIMESTAMP值的执行受以下异常情况的影响:

调用触发器或导致AUTO_INCREMENT列更新的函数的语句在基于语句的复制中无法正确复制。这些语句被标记为不安全。(Bug #45677)

对于具有包含AUTO_INCREMENT列但不是这个复合主键的第一列的复合主键的表进行INSERT不适用于基于语句的日志记录或复制。这些语句被标记为不安全。(Bug #11754117, Bug #45670)

这个问题不影响使用InnoDB存储引擎的表,因为InnoDB表的AUTO_INCREMENT列需要至少一个键,其中AUTO_INCREMENT列是唯一的或最左边的列。

向具有ALTER TABLE的表添加AUTO_INCREMENT列可能不会在副本和源上产生相同的行顺序。这是因为行编号的顺序取决于用于表的特定存储引擎以及插入行的顺序。如果在源和副本上具有相同的顺序很重要,则在分配AUTO_INCREMENT编号之前必须对行进行排序。假设您想向具有列col1col2的表t1添加AUTO_INCREMENT列,以下语句将生成一个与t1相同但具有AUTO_INCREMENT列的新表t2

代码语言:javascript
复制
CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 ADD id INT AUTO_INCREMENT PRIMARY KEY;
INSERT INTO t2 SELECT * FROM t1 ORDER BY col1, col2;

重要提示

为了保证源和副本的顺序相同,ORDER BY子句必须命名t1所有列。

刚刚给出的指令受到CREATE TABLE ... LIKE的限制:外键定义被忽略,DATA DIRECTORYINDEX DIRECTORY表选项也被忽略。如果表定义包含任何这些特征,使用与创建t1相同的CREATE TABLE语句创建t2,但增加AUTO_INCREMENT列。

无论用于创建和填充具有AUTO_INCREMENT列的副本的方法如何,最后一步是删除原始表,然后重命名副本:

代码语言:javascript
复制
DROP t1;
ALTER TABLE t2 RENAME t1;

另请参阅 Section B.3.6.1, “Problems with ALTER TABLE”。

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

19.5.1.2 复制和 BLACKHOLE 表

BLACKHOLE存储引擎接受数据但会丢弃它,不会存储。在执行二进制日志记录时,所有对这些表的插入操作都会被记录,无论使用的日志格式是什么。根据使用的基于语句或基于行的日志记录方式,更新和删除操作会有不同的处理方式。在基于语句的日志记录格式下,所有影响BLACKHOLE表的语句都会被记录,但它们的效果会被忽略。在使用基于行的日志记录时,对这些表的更新和删除操作会被简单地跳过,不会被写入二进制日志。每当发生这种情况时,都会记录一个警告。

出于这个原因,我们建议当您使用BLACKHOLE存储引擎复制表时,将binlog_format服务器变量设置为STATEMENT,而不是ROWMIXED

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

19.5.1.3 复制和字符集

在使用不同字符集的 MySQL 服务器之间进行复制时,以下内容适用:

  • 如果源数据库具有与全局character_set_server值不同的字符集,则应设计CREATE TABLE语句,使其不会隐式依赖于数据库默认字符集。一个好的解决方法是在CREATE TABLE语句中明确指定字符集和校对规则。

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

19.5.1.4 复制和 CHECKSUM TABLE

CHECKSUM TABLE 返回一个逐行计算的校验和,使用依赖于表行存储格式的方法。存储格式在 MySQL 版本之间不保证保持不变,因此在升级后校验和值可能会改变。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-create-alter-drop-server.html

19.5.1.5 复制CREATE SERVERALTER SERVERDROP SERVER

CREATE SERVERALTER SERVERDROP SERVER语句不管使用何种二进制日志格式,都不会被写入二进制日志中。

原文:dev.mysql.com/doc/refman/8.0/en/replication-features-create-if-not-exists.html

19.5.1.6 复制CREATE ... IF NOT EXISTS语句

当复制各种CREATE ... IF NOT EXISTS语句时,MySQL 会应用以下规则:

  • 每个CREATE DATABASE IF NOT EXISTS语句都会被复制,无论源数据库是否已存在。
  • 类似地,每个不带SELECTCREATE TABLE IF NOT EXISTS语句都会被复制,无论源端表是否已存在。这包括CREATE TABLE IF NOT EXISTS ... LIKECREATE TABLE IF NOT EXISTS ... SELECT的复制遵循稍有不同的规则;更多信息请参见第 19.5.1.7 节,“复制CREATE TABLE ... SELECT语句”。
  • CREATE EVENT IF NOT EXISTS始终会被复制,无论语句中指定的事件是否已存在于源端。
  • 只有成功的CREATE USER语句才会被写入二进制日志。如果语句包含IF NOT EXISTS,则被视为成功,并在至少创建一个在语句中命名的用户时记录;在这种情况下,语句将被记录为原样;这包括对未创建的现有用户的引用。更多信息请参见创建用户二进制日志记录。
  • (MySQL 8.0.29 及更高版本😃 CREATE PROCEDURE IF NOT EXISTSCREATE FUNCTION IF NOT EXISTSCREATE TRIGGER IF NOT EXISTS,如果成功,将完整写入二进制日志(包括IF NOT EXISTS子句),无论语句是否因对象(过程、函数或触发器)已存在而引发警告。

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

19.5.1.7 复制 CREATE TABLE … SELECT 语句

当复制CREATE TABLE ... SELECT语句时,MySQL 应用以下规则:

  • CREATE TABLE ... SELECT总是执行隐式提交(第 15.3.3 节,“导致隐式提交的语句”)。
  • 如果目标表不存在,则记录如下。无论是否存在IF NOT EXISTS都无关紧要。
    • STATEMENTMIXED格式:该语句按原样记录。
    • ROW格式:该语句被记录为一个CREATE TABLE语句,后跟一系列插入行事件。 在 MySQL 8.0.21 之前,该语句被记录为两个事务。从 MySQL 8.0.21 开始,在支持原子 DDL 的存储引擎上,它被记录为一个事务。更多信息,请参阅第 15.1.1 节,“原子数据定义语句支持”。
  • 如果CREATE TABLE ... SELECT语句失败,则不会记录任何内容。这包括目标表存在且未使用IF NOT EXISTS的情况。
  • 如果目标表存在且使用了IF NOT EXISTS,MySQL 8.0 会完全忽略该语句;不会插入任何内容或记录日志。

MySQL 8.0 不允许CREATE TABLE ... SELECT语句对除了该语句创建的表之外的其他表进行任何更改。

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

19.5.1.8 CURRENT_USER() 的复制

以下语句支持使用CURRENT_USER()函数来代替受影响用户或定义者的名称,以及可能的主机:

  • DROP USER
  • RENAME USER
  • GRANT
  • REVOKE
  • CREATE FUNCTION
  • CREATE PROCEDURE
  • CREATE TRIGGER
  • CREATE EVENT
  • CREATE VIEW
  • ALTER EVENT
  • ALTER VIEW
  • SET PASSWORD

当启用二进制日志记录并且在这些语句中使用CURRENT_USER()CURRENT_USER作为定义者时,MySQL 服务器确保在语句被复制时应用于源和副本上的相同用户。在某些情况下,例如更改密码的语句,函数引用在写入二进制日志之前会被展开,以便语句包含用户名称。对于所有其他情况,源上的当前用户名称会作为元数据被复制到副本上,并且副本会将语句应用于元数据中命名的当前用户,而不是副本上的当前用户。

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

19.5.1.9 源表和副本表定义不同的复制

源表和目标表的复制不必完全相同。源表可以比副本表的副本具有更多或更少的列。此外,源表和副本的对应表列可以使用不同的数据类型,但必须满足一定条件。

注意

不支持不同分区的表之间的复制。参见 Section 19.5.1.24, “复制和分区”。

在所有源表和目标表定义不完全相同的情况下,数据库和表名必须在源表和副本上相同。在以下两个部分中讨论了其他条件,并给出了示例。

19.5.1.9.1 源表或副本表中有更多列的复制

可以将表从源复制到副本,使得源表和副本表的列数不同,但必须满足以下条件:

两个表共有的列必须在源表和副本上以相同顺序定义。(即使两个表具有相同数量的列也是如此。)

两个表共有的列必须在任何额外列之前定义。

这意味着在副本上执行ALTER TABLE语句,向表中插入一个新列,该列位于两个表共有的列范围内,会导致复制失败,如下例所示:

假设表t在源和副本上存在,并由以下CREATE TABLE语句定义:

代码语言:javascript
复制
CREATE TABLE t (
    c1 INT,
    c2 INT,
    c3 INT
);

假设在副本上执行了以下ALTER TABLE语句:

代码语言:javascript
复制
ALTER TABLE t ADD COLUMN cnew1 INT AFTER c3;

之前的ALTER TABLE在副本上是允许的,因为表t的两个版本中共有的列c1c2c3在任何不同的列之前都保持在一起。

然而,在副本上执行以下ALTER TABLE语句会导致复制中断:

代码语言:javascript
复制
ALTER TABLE t ADD COLUMN cnew2 INT AFTER c2;

在副本上执行刚刚显示的ALTER TABLE语句后,复制失败,因为新列cnew2位于t两个版本共有的列之间。

在列更多的表版本中,每个“额外”列必须有一个默认值。

列的默认值由多种因素决定,包括其类型、是否使用DEFAULT选项定义、是否声明为NULL,以及创建时服务器 SQL 模式的有效性;更多信息,请参见第 13.6 节,“数据类型默认值”)。

此外,当副本表比源表具有更多列时,两个表中共有的每一列必须在两个表中使用相同的数据类型。

示例。 以下示例说明了一些有效和无效的表定义:

源表中有更多列。 以下表定义是有效的,并且可以正确复制:

代码语言:javascript
复制
source> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
replica>  CREATE TABLE t1 (c1 INT, c2 INT);

下表定义会引发错误,因为两个版本表共有的列的定义在副本表上的顺序与源表上的顺序不同:

代码语言:javascript
复制
source> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
replica>  CREATE TABLE t1 (c2 INT, c1 INT);

下表定义也会引发错误,因为源表中额外列的定义出现在两个版本共有的列定义之前:

代码语言:javascript
复制
source> CREATE TABLE t1 (c3 INT, c1 INT, c2 INT);
replica>  CREATE TABLE t1 (c1 INT, c2 INT);

副本表中有更多列。 以下表定义是有效的,并且可以正确复制:

代码语言:javascript
复制
source> CREATE TABLE t1 (c1 INT, c2 INT);
replica>  CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);

下列定义会引发错误,因为两个版本表共有的列在源表和副本表上的定义顺序不同:

代码语言:javascript
复制
source> CREATE TABLE t1 (c1 INT, c2 INT);
replica>  CREATE TABLE t1 (c2 INT, c1 INT, c3 INT);

下表定义也会引发错误,因为副本版本表中额外列的定义出现在两个版本共有的列定义之前:

代码语言:javascript
复制
source> CREATE TABLE t1 (c1 INT, c2 INT);
replica>  CREATE TABLE t1 (c3 INT, c1 INT, c2 INT);

下表定义失败,因为副本版本表比源版本表多了额外列,并且两个版本的表对于共有列c2使用了不同的数据类型:

代码语言:javascript
复制
source> CREATE TABLE t1 (c1 INT, c2 BIGINT);
replica>  CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
19.5.1.9.2 具有不同数据类型的列的复制

源表和副本表中相应的列的副本应该具有相同的数据类型。然而,并不总是严格执行这一规定,只要满足一定条件即可。

通常可以从具有特定数据类型的列复制到具有相同类型和大小或宽度的另一列,如适用,或更大的列。例如,可以从CHAR(10)列复制到另一个CHAR(10)列,或者从CHAR(10)列复制到CHAR(25)列而不会出现问题。在某些情况下,还可以从源表中具有一种数据类型的列复制到副本中具有不同数据类型的列;当源表中列的数据类型提升为副本中相同大小或更大的类型时,这称为属性提升。

属性提升可用于基于语句和基于行的复制,并且不依赖于源或副本使用的存储引擎。但是,日志格式的选择确实会影响允许的类型转换;具体内容将在本节后面讨论。

重要提示

无论您使用基于语句还是基于行的复制,如果希望使用属性提升,则副本表的副本不能包含比源表的副本更多的列。

基于语句的复制。 在使用基于语句的复制时,一个简单的经验法则是,“如果在源上运行的语句也可以在副本上成功执行,则它也应该成功复制”。换句话说,如果语句使用与副本上给定列类型兼容的值,则可以复制该语句。例如,您可以将适合TINYINT列的任何值插入到BIGINT列中;因此,即使您将副本表中的TINYINT列的类型更改为BIGINT,任何成功插入该列的源上的插入也应该在副本上成功,因为不可能有一个合法的TINYINT值大到足以超过BIGINT列。

基于行的复制:属性提升和降级。 基于行的复制支持较小数据类型和较大类型之间的属性提升和降级。还可以指定是否允许对降级列值进行有损(截断)或无损转换,如本节后面所述。

有损和无损转换。 在目标类型无法表示要插入的值的情况下,必须决定如何处理转换。如果我们允许转换但截断(或以其他方式修改)源值以在目标列中实现“适合”,我们进行的是所谓的有损转换。不需要截断或类似修改以使源列值适合目标列的转换是无损转换。

类型转换模式。 系统变量replica_type_conversions(从 MySQL 8.0.26 开始)或slave_type_conversions(在 MySQL 8.0.26 之前)的全局值控制副本上使用的类型转换模式。此变量接受以下列表中的一组值,描述了每种模式对副本的类型转换行为的影响:

ALL_LOSSY

在此模式下,允许会导致信息丢失的类型转换。

这并不意味着允许非损失转换,仅表示只允许需要损失转换或根本不需要转换的情况;例如,仅启用模式允许将INT列转换为TINYINT(损失转换),但不允许将TINYINT列转换为INT列(非损失)。在这种情况下尝试后者的转换会导致副本停止并显示错误。

ALL_NON_LOSSY

此模式允许不需要截断或其他特殊处理源值的转换;也就是说,它允许目标类型的范围比源类型更宽的转换。

设置此模式不影响是否允许有损转换;这由ALL_LOSSY模式控制。如果只设置了ALL_NON_LOSSY,但没有设置ALL_LOSSY,那么尝试进行可能导致数据丢失的转换(例如INTTINYINT,或CHAR(25)VARCHAR(20))会导致副本停止并显示错误。

ALL_LOSSY,ALL_NON_LOSSY

当设置此模式时,允许所有支持的类型转换,无论它们是否是有损转换。

ALL_SIGNED

将提升的整数类型视为有符号值(默认行为)。

ALL_UNSIGNED

将提升的整数类型视为无符号值。

ALL_SIGNED,ALL_UNSIGNED

尽可能将提升的整数类型视为有符号,否则视为无符号。

[]

当未设置replica_type_conversionsslave_type_conversions时,不允许进行属性提升或降级;这意味着源表和目标表中的所有列必须是相同类型。

这是默认模式。

当整数类型被提升时,其符号性不会被保留。默认情况下,副本将所有这些值视为有符号的。您可以使用ALL_SIGNEDALL_UNSIGNED或两者来控制此行为。ALL_SIGNED告诉副本将所有提升的整数类型视为有符号;ALL_UNSIGNED指示将其视为无符号。如果同时指定两者,副本将尽可能将值视为有符号,否则将视为无符号;它们列出的顺序并不重要。如果至少没有使用ALL_LOSSYALL_NONLOSSY中的一个,那么ALL_SIGNEDALL_UNSIGNED都不会产生任何效果。

更改类型转换模式需要使用新的replica_type_conversionsslave_type_conversions设置重新启动副本。

支持的转换。 支持不同但相似数据类型之间的转换列在以下列表中:

  • 在任何整数类型TINYINTSMALLINTMEDIUMINTINTBIGINT之间。 这包括这些类型的有符号和无符号版本之间的转换。 通过将源值截断为目标列允许的最大(或最小)值来进行有损转换。为了确保从无符号到有符号类型的非有损转换,目标列必须足够大,以容纳源列中的值范围。例如,您可以将TINYINT UNSIGNED非有损地降级为SMALLINT,但不能降级为TINYINT
  • 在任何十进制类型DECIMALFLOATDOUBLENUMERIC之间。 FLOATDOUBLE是非有损转换;DOUBLEFLOAT只能以有损方式处理。从DECIMAL(*M*,*D*)DECIMAL(*M’*,*D’*)的转换,其中*D’* >= *D*(*M’*-*D’*) >= (*M*-*D*)是非有损的;对于任何*M’* < *M**D’* < *D*,或两者都是的情况,只能进行有损转换。 对于任何十进制类型,如果要存储的值无法适应目标类型,则根据文档中其他地方定义的服务器舍入规则将该值向下舍入。有关十进制类型的此类操作的详细信息,请参见第 14.24.4 节,“舍入行为”。
  • 在任何字符串类型CHARVARCHARTEXT之间,包括不同宽度之间的转换。 将CHARVARCHARTEXT转换为大小相同或更大的CHARVARCHARTEXT列永远不会有损。有损转换通过在副本上仅插入字符串的前*N个字符来处理,其中N*是目标列的宽度。 重要提示 不支持在使用不同字符集的列之间进行复制。
  • 任意二进制数据类型BINARYVARBINARYBLOB之间的转换,包括不同宽度之间的转换。 将BINARYVARBINARYBLOB转换为相同大小或更大的BINARYVARBINARYBLOB列永远不会有损失。有损转换通过仅在副本上插入字符串的前*N字节来处理,其中N*是目标列的宽度。
  • 任意两个不同大小的BIT列之间。 当将来自BIT(*M*)列的值插入到BIT(*M’*)列中,其中*M’* > *M*时,BIT(*M’*)列的最高有效位被清除(设置为零),而BIT(*M*)值的*M*位被设置为BIT(*M’*)列的最低有效位。 当将来自源BIT(*M*)列的值插入到目标BIT(*M’*)列中,其中*M’* < *M*时,BIT(*M’*)列被赋予最大可能的值;换句话说,目标列被赋予“全置位”值。

类型转换不在前述列表中的类型是不允许的。

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

19.5.1.10 复制和 DIRECTORY 表选项

如果在源服务器的CREATE TABLE语句中使用了DATA DIRECTORYINDEX DIRECTORY表选项,则该表选项也会在副本上使用。如果在副本主机文件系统中不存在相应的目录,或者存在但对副本 MySQL 服务器不可访问,则可能会出现问题。可以通过在副本上使用NO_DIR_IN_CREATE服务器 SQL 模式来覆盖此行为,这会导致副本在复制CREATE TABLE语句时忽略DATA DIRECTORYINDEX DIRECTORY表选项。结果是MyISAM数据和索引文件将在表的数据库目录中创建。

查看更多信息,请参见第 7.1.11 节,“服务器 SQL 模式”。

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

19.5.1.11 复制DROP ... IF EXISTS语句

DROP DATABASE IF EXISTSDROP TABLE IF EXISTSDROP VIEW IF EXISTS语句始终会被复制,即使要删除的数据库、表或视图在源上不存在。这是为了确保一旦副本赶上源,要删除的对象在源或副本上都不再存在。

DROP ... IF EXISTS 语句用于存储程序(存储过程和函数,触发器和事件),即使要删除的存储程序在源上不存在,也会被复制。

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

19.5.1.12 复制和浮点值

在基于语句的复制中,值从十进制转换为二进制。由于十进制和二进制表示之间的转换可能是近似的,涉及浮点值的比较是不精确的。这对明确使用浮点值的操作,或者隐式转换为浮点的值都是适用的。由于计算机架构、用于构建 MySQL 的编译器等方面的差异,源服务器和副本服务器上对浮点值的比较可能产生不同的结果。参见第 14.3 节,“表达式评估中的类型转换”,以及第 B.3.4.8 节,“浮点值的问题”。

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

19.5.1.13 复制和 FLUSH

一些形式的FLUSH语句不会被记录,因为如果被复制到副本中可能会引起问题:FLUSH LOGSFLUSH TABLES WITH READ LOCK。有关语法示例,请参见 Section 15.7.8.3, “FLUSH Statement”。FLUSH TABLESANALYZE TABLEOPTIMIZE TABLEREPAIR TABLE语句会被写入二进制日志,因此会被复制到副本中。通常这不是问题,因为这些语句不会修改表数据。

然而,在某些情况下,这种行为可能会引起困难。如果在mysql数据库中复制权限表并直接更新这些表而不使用GRANT,则必须在副本上发出FLUSH PRIVILEGES以使新权限生效。此外,如果在重命名作为MERGE表的MyISAM表时使用FLUSH TABLES,则必须在副本上手动发出FLUSH TABLES。除非指定NO_WRITE_TO_BINLOG或其别名LOCAL,否则这些语句将被写入二进制日志。

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

19.5.1.14 复制和系统函数

在某些情况下,某些函数无法很好地进行复制:

USER()CURRENT_USER()(或CURRENT_USER)、UUID()VERSION()LOAD_FILE()函数在复制时不会更改,因此在副本上无法可靠工作,除非启用了基于行的复制。(参见 Section 19.2.1, “复制格式”。)

MIXED模式下使用基于行的复制时,USER()CURRENT_USER()会自动复制,并在STATEMENT模式下生成警告。(另请参阅 Section 19.5.1.8, “CURRENT_USER()的复制”的复制")。)对于VERSION()RAND()也是如此。

对于NOW(),二进制日志包括时间戳。这意味着源上调用此函数返回的值会被复制到副本中。为了避免在不同时区的 MySQL 服务器之间复制时出现意外结果,请在源和副本上都设置时区。更多信息,请参见 Section 19.5.1.33, “复制和时区”。

为了解释在不同时区的服务器之间复制时可能出现的问题,假设源位于纽约,副本位于斯德哥尔摩,两台服务器都使用当地时间。进一步假设,在源上,你创建了一个表mytable,对该表执行了一个INSERT语句,然后从表中选择,如下所示:

代码语言:javascript
复制
mysql> CREATE TABLE mytable (mycol TEXT);
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO mytable VALUES ( NOW() );
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM mytable;
+---------------------+
| mycol               |
+---------------------+
| 2009-09-01 12:00:00 |
+---------------------+
1 row in set (0.00 sec)

斯德哥尔摩的当地时间比纽约晚 6 小时;因此,如果你在副本上的确切时刻发出SELECT NOW(),将返回值2009-09-01 18:00:00。因此,如果在复制了刚刚显示的CREATE TABLEINSERT语句之后,从副本的mytable复制,你可能期望mycol包含值2009-09-01 18:00:00。然而,事实并非如此;当你从副本的mytable复制时,你得到的结果与源上完全相同:

代码语言:javascript
复制
mysql> SELECT * FROM mytable;
+---------------------+
| mycol               |
+---------------------+
| 2009-09-01 12:00:00 |
+---------------------+
1 row in set (0.00 sec)

NOW()不同,SYSDATE()函数不是复制安全的,因为它不受二进制日志中SET TIMESTAMP语句的影响,并且在使用基于语句的日志记录时是不确定的。如果使用基于行的日志记录,则不会出现问题。

另一种选择是使用--sysdate-is-now选项,使SYSDATE()成为NOW()的别名。这必须在源和副本上都执行才能正常工作。在这种情况下,此函数仍会发出警告,但只要在源和副本上都使用--sysdate-is-now,就可以安全地忽略。

当使用MIXED模式时,SYSDATE()会自动使用基于行的复制进行复制,并在STATEMENT模式下生成警告。

另请参阅 Section 19.5.1.33, “Replication and Time Zones”。

以下限制仅适用于基于语句的复制,不适用于基于行的复制。 处理用户级锁的GET_LOCK()RELEASE_LOCK()IS_FREE_LOCK()IS_USED_LOCK()函数在源上处理并在副本上不知道并发上下文。因此,这些函数不应用于插入源表,因为副本上的内容会有所不同。例如,不要发出类似INSERT INTO mytable VALUES(GET_LOCK(...))的语句。

当使用MIXED模式时,这些函数会自动使用基于行的复制进行复制,并在STATEMENT模式下生成警告。

作为解决方案,当基于语句的复制生效时,您可以使用将有问题的函数结果保存在用户变量中,并在后续语句中引用该变量的策略。例如,以下单行INSERT由于引用UUID()函数而存在问题:

代码语言:javascript
复制
INSERT INTO t VALUES(UUID());

要解决这个问题,可以这样做��

代码语言:javascript
复制
SET @my_uuid = UUID();
INSERT INTO t VALUES(@my_uuid);

该序列的语句之所以能够复制,是因为@my_uuid的值作为用户变量事件存储在二进制日志中,先于INSERT语句,并且可以在INSERT中使用。

相同的思路也适用于多行插入,但使用起来更加繁琐。对于两行插入,您可以这样做:

代码语言:javascript
复制
SET @my_uuid1 = UUID(); @my_uuid2 = UUID();
INSERT INTO t VALUES(@my_uuid1),(@my_uuid2);

但是,如果行数很大或者未知,解决方法就会变得困难或者不可行。例如,你无法将以下语句转换为一个语句,其中一个给定的个人用户变量与每一行相关联:

代码语言:javascript
复制
INSERT INTO t2 SELECT UUID(), * FROM t1;

在存储函数中,RAND() 只要在函数执行过程中仅调用一次,就能正确复制。(你可以将函数执行时间戳和随机数种子视为在源和副本上相同的隐式输入。)

FOUND_ROWS()ROW_COUNT() 函数在基于语句的复制中无法可靠复制。一个解决方法是将函数调用的结果存储在用户变量中,然后在 INSERT 语句中使用。例如,如果你希望将结果存储在名为 mytable 的表中,你可能会像这样做:

代码语言:javascript
复制
SELECT SQL_CALC_FOUND_ROWS FROM mytable LIMIT 1;
INSERT INTO mytable VALUES( FOUND_ROWS() );

但是,如果你正在复制 mytable,你应该使用 SELECT ... INTO,然后将变量存储在表中,就像这样:

代码语言:javascript
复制
SELECT SQL_CALC_FOUND_ROWS INTO @found_rows FROM mytable LIMIT 1;
INSERT INTO mytable VALUES(@found_rows);

这样,用户变量将作为上下文的一部分进行复制,并在副本上正确应用。

当使用 MIXED 模式时,这些函数会在基于行的复制中自动复制,并在 STATEMENT 模式下生成警告。(Bug #12092, Bug #30244)

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

19.5.1.15 复制和分数秒支持

MySQL 8.0 允许TIMEDATETIMETIMESTAMP值使用微秒(6 位数字)精度的分数秒。请参见第 13.2.6 节,“时间值中的分数秒”。

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

19.5.1.16 调用特性的复制

调用特性的复制,如可加载函数和存储程序(存储过程和函数、触发器和事件),提供以下特性:

  • 特性的效果始终会被复制。
  • 以下语句使用基于语句的复制进行复制:
    • CREATE EVENT
    • ALTER EVENT
    • DROP EVENT
    • CREATE PROCEDURE
    • DROP PROCEDURE
    • CREATE FUNCTION
    • DROP FUNCTION
    • CREATE TRIGGER
    • DROP TRIGGER

    但是,使用这些语句创建、修改或删除的特性的效果是使用基于行的复制进行复制的。 注意 尝试使用基于语句的复制复制调用特性会产生警告“Statement is not safe to log in statement format”。例如,尝试使用基于语句的复制复制可加载函数会生成此警告,因为当前无法由 MySQL 服务器确定函数是否是确定性的。如果您绝对确定调用特性的效果是确定性的,可以安全地忽略此类警告。

  • CREATE EVENTALTER EVENT的情况下:
    • 事件的状态在副本上设置为SLAVESIDE_DISABLED,无论指定的状态如何(这不适用于DROP EVENT)。
    • 在副本上,通过其服务器 ID 标识创建事件的源。INFORMATION_SCHEMA.EVENTS中的ORIGINATOR列存储此信息。有关更多信息,请参见第 15.7.7.18 节,“SHOW EVENTS Statement”。
  • 该功能的实现位于副本中,处于可更新状态,因此如果源失败,副本可以被用作源而不会丢失事件处理。

要确定在 MySQL 服务器上是否有任何在不同服务器(作为源服务器)上创建的计划事件,请以类似于此处所示的方式查询信息模式EVENTS表:

代码语言:javascript
复制
SELECT EVENT_SCHEMA, EVENT_NAME
    FROM INFORMATION_SCHEMA.EVENTS
    WHERE STATUS = 'SLAVESIDE_DISABLED';

或者,您可以使用SHOW EVENTS语句,如下所示:

代码语言:javascript
复制
SHOW EVENTS
    WHERE STATUS = 'SLAVESIDE_DISABLED';

将具有此类事件的副本升级为源时,必须使用ALTER EVENT *event_name* ENABLE来启用每个事件,其中*event_name*是事件的名称。

如果在创建此副本上的事件时涉及多个源,并且您希望识别仅在具有服务器 ID *source_id*的给定源上创建的事件,请修改前面在EVENTS表上的查询,包括ORIGINATOR列,如下所示:

代码语言:javascript
复制
SELECT EVENT_SCHEMA, EVENT_NAME, ORIGINATOR
    FROM INFORMATION_SCHEMA.EVENTS
    WHERE STATUS = 'SLAVESIDE_DISABLED'
    AND   ORIGINATOR = '*source_id*'

您可以以类似的方式使用SHOW EVENTS语句中的ORIGINATOR

代码语言:javascript
复制
SHOW EVENTS
    WHERE STATUS = 'SLAVESIDE_DISABLED'
    AND   ORIGINATOR = '*source_id*'

在启用从源复制的事件之前,您应该在副本上禁用 MySQL 事件调度程序(使用类似于SET GLOBAL event_scheduler = OFF;的语句),运行任何必要的ALTER EVENT语句,重新启动服务器,然后在副本上重新启用事件调度程序(使用类似于SET GLOBAL event_scheduler = ON;的语句)-

如果稍后将新源重新降级为副本,则必须手动禁用由ALTER EVENT语句启用的所有事件。您可以通过在单独的表中存储先前显示的SELECT语句中的事件名称,或使用ALTER EVENT语句将事件重命名为具有replicated_前缀的公共前缀来执行此操作。

如果您重命名事件,那么在将此服务器重新降级为副本时,您可以通过查询EVENTS表来识别事件,如下所示:

代码语言:javascript
复制
SELECT CONCAT(EVENT_SCHEMA, '.', EVENT_NAME) AS 'Db.Event'
      FROM INFORMATION_SCHEMA.EVENTS
      WHERE INSTR(EVENT_NAME, 'replicated_') = 1;

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

19.5.1.17 JSON 文档的复制

在 MySQL 8.0 之前,对 JSON 列的更新始终被写入二进制日志作为完整文档。在 MySQL 8.0 中,可以记录 JSON 文档的部分更新(请参阅 JSON 值的部分更新),这更有效率。记录行为取决于所使用的格式,如下所述:

基于语句的复制。 JSON 部分更新始终被记录为部分更新。在使用基于语句的日志记录时,无法禁用此功能。

基于行的复制。 默认情况下,JSON 部分更新不会被记录为部分更新,而是被记录为完整文档。要启用部分更新的记录,请设置binlog_row_value_options=PARTIAL_JSON。如果复制源设置了此变量,则来自该源的部分更新将由副本处理和应用,而不管副本自身对该变量的设置如何。

运行 MySQL 8.0.2 或更早版本的服务器无法识别用于 JSON 部分更新的日志事件。因此,当从运行 MySQL 8.0.3 或更高版本的服务器复制到此类服务器时,必须通过将此变量设置为''(空字符串)在源端禁用binlog_row_value_options。有关更多信息,请参阅此变量的描述。

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

19.5.1.18 复制和 LIMIT

DELETEUPDATEINSERT ... SELECT语句中,基于语句的复制LIMIT子句是不安全的,因为受影响的行的顺序未定义。(只有当这些语句还包含ORDER BY子句时,才能通过基于语句的复制正确复制这些语句。)当遇到这样的语句时:

  • 在使用STATEMENT模式时,现在会发出警告,说明该语句对于基于语句的复制不安全。 在使用STATEMENT模式时,即使 DML 语句包含LIMIT并且还有ORDER BY子句(因此变得确定性),也会发出警告。这是一个已知问题。(Bug #42851)
  • 在使用MIXED模式时,该语句现在会自动使用基于行的模式进行复制。

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

19.5.1.19 复制和 LOAD DATA

LOAD DATA 被认为在基于语句的日志记录中是不安全的(参见 Section 19.2.1.3, “二进制日志中安全和不安全语句的确定”)。当设置 binlog_format=MIXED 时,该语句以行格式记录。当设置 binlog_format=STATEMENT 时,请注意,与其他不安全语句不同,LOAD DATA 不会生成警告。

如果您使用 LOAD DATAbinlog_format=STATEMENT,每个要应用更改的副本都会创建一个包含数据的临时文件。然后,副本使用 LOAD DATA 语句来应用更改。即使源上启用了二进制日志加密,此临时文件也不会被加密。如果需要加密,请改用基于行或混合的二进制日志格式,副本不会创建临时文件。

如果使用 PRIVILEGE_CHECKS_USER 帐户来帮助保护复制通道(参见 Section 19.3.3, “复制权限检查”),强烈建议您使用基于行的二进制日志记录(binlog_format=ROW)记录 LOAD DATA 操作。如果为通道设置了 REQUIRE_ROW_FORMAT,则需要基于行的二进制日志记录。使用此日志格式,执行事件不需要 FILE 权限,因此不要给 PRIVILEGE_CHECKS_USER 帐户此权限。如果需要从以语句格式记录的 LOAD DATA INFILE 操作的复制错误中恢复,并且复制的事件是可信的,则可以暂时授予 PRIVILEGE_CHECKS_USER 帐户 FILE 权限,在应用复制的事件后再删除该权限。

mysqlbinlog读取以语句为基础格式记录的LOAD DATA语句的日志事件时,会在临时目录中创建一个生成的本地文件。这些临时文件不会被mysqlbinlog或任何其他 MySQL 程序自动删除。如果您确实使用了以语句为基础的二进制日志记录的LOAD DATA语句,那么在不再需要语句日志后,您应该自行删除这些临时文件。更多信息,请参阅 Section 6.6.9, “mysqlbinlog — 用于处理二进制日志文件的实用程序”。

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

19.5.1.20 复制和 max_allowed_packet

max_allowed_packet设置了 MySQL 服务器和客户端之间的任何单个消息的大小上限,包括副本。如果在源端复制大型列值(例如可能在TEXTBLOB列中找到的值),而max_allowed_packet在源端设置过小,源端将会出现错误,并且副本会关闭复制 I/O(接收器)线程。如果副本端的max_allowed_packet设置过小,也会导致副本停止 I/O 线程。

基于行的复制从源端向副本发送更新行的所有列和列值,包括实际上未被更新的列的值。这意味着,当您使用基于行的复制复制大型列值时,您必须确保将max_allowed_packet设置得足够大,以容纳要复制的任何表中最大行的大小,即使您只复制更新,或者只插入相对较小的值。

在多线程复制(具有replica_parallel_workers > 0slave_parallel_workers > 0)中,确保系统变量replica_pending_jobs_size_maxslave_pending_jobs_size_max的设置值等于或大于源端max_allowed_packet系统变量的设置值。replica_pending_jobs_size_maxslave_pending_jobs_size_max的默认设置为 128M,是max_allowed_packet系统变量的默认设置值 64M 的两倍。max_allowed_packet限制了源端可以发送的数据包大小,但添加事件头可能会产生超过此大小的二进制日志事件。此外,在基于行的复制中,单个事件可能比max_allowed_packet大小显著更大,因为max_allowed_packet的值仅限制表的每列。

实际上,复制端接受的数据包上限由其replica_max_allowed_packetslave_max_allowed_packet设置确定,默认设置为最大设置值 1GB,以防止由于大数据包而导致复制失败。然而,replica_pending_jobs_size_maxslave_pending_jobs_size_max的值控制了复制端可用于保存传入数据包的内存。指定的内存是在所有复制工作队列之间共享的。

replica_pending_jobs_size_maxslave_pending_jobs_size_max的值是一个软限制,如果一个异常大的事件(由一个或多个数据包组成)超过了这个大小,事务将被暂停,直到所有副本工作者的队列为空,然后再处理。所有后续事务都将被暂停,直到大事务完成。因此,虽然大于replica_pending_jobs_size_maxslave_pending_jobs_size_max的异常事件可以被处理,但清空所有副本工作者队列和等待排队后续事务的延迟可能导致副本延迟和副本工作者并发性降低。因此,replica_pending_jobs_size_maxslave_pending_jobs_size_max应设置为足够高,以容纳大多数预期事件大小。

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

19.5.1.21 复制和 MEMORY 表

当复制源服务器关闭并重新启动时,其MEMORY表会变为空。为了将这种效果复制到副本中,源在启动后第一次使用给定的MEMORY表时,会记录一个事件,通知副本该表必须通过向二进制日志写入DELETE或(从 MySQL 8.0.22 开始)TRUNCATE TABLE语句来清空该表。这个生成的事件在二进制日志中通过注释可识别,如果服务器上使用了 GTID,则会分配一个 GTID。该语句始终以语句格式记录,即使二进制日志格式设置为ROW,并且即使服务器设置为read_onlysuper_read_only模式,也会写入。请注意,在源重新启动并首次使用表之间的间隔期间,副本仍然具有MEMORY表中的过时数据。为了避免这种间隔,当直接查询副本可能返回陈旧数据时,您可以设置init_file系统变量以命名一个包含在启动时在源上填充MEMORY表的语句的文件。

当副本服务器关闭并重新启动时,其MEMORY表会变为空。这会导致副本与源不同步,并可能导致其他故障或导致副本停止:

  • 来自源的行格式更新和删除可能会因为Can't find record in '*memory_table*'而失败。
  • 诸如INSERT INTO ... SELECT FROM *memory_table*之类的语句可能在源和副本上插入不同的行集。

副本还会将一个DELETE或(从 MySQL 8.0.22 开始)TRUNCATE TABLE语句写入其自己的二进制日志,传递给任何下游副本,导致它们清空自己的MEMORY表。

重新启动正在复制MEMORY表的副本的安全方法是首先在源上删除或清空所有MEMORY表中的行,并等待这些更改复制到副本。然后才能安全地重新启动副本。

在某些情况下可能适用另一种重启方法。当binlog_format=ROW时,如果在重新启动复制之前设置replica_exec_mode=IDEMPOTENT(从 MySQL 8.0.26 开始)或slave_exec_mode=IDEMPOTENT(在 MySQL 8.0.26 之前),则可以防止复制停止。这样可以使复制继续进行,但其MEMORY表仍然与源端不同。如果应用逻辑允许MEMORY表的内容安全丢失(例如,如果MEMORY表用于缓存),那么这是可以接受的。replica_exec_mode=IDEMPOTENTslave_exec_mode=IDEMPOTENT对所有表都适用,因此可能会隐藏非MEMORY表中的其他复制错误。

(刚刚描述的方法在 NDB Cluster 中不适用,那里的replica_exec_modeslave_exec_mode始终为IDEMPOTENT,且无法更改。)

MEMORY表的大小受max_heap_table_size系统变量的值限制,该值不会被复制(参见 Section 19.5.1.39,“复制和变量”)。更改max_heap_table_size对于使用ALTER TABLE ... ENGINE = MEMORYTRUNCATE TABLE创建或更新的MEMORY表会生效,或者对于所有在服务器重新启动后的MEMORY表也会生效。如果你在源端增加了此变量的值而在复制端没有这样做,那么源端的表可能会比复制端的表更大,导致在源端成功插入但在复制端出现“表已满”错误。这是一个已知问题(Bug #48666)。在这种情况下,你必须在复制端和源端都设置max_heap_table_size的全局值,然后重新启动复制。建议同时重新启动源端和复制端的 MySQL 服务器,以确保新值在它们各自上完全生效。

查看第 18.3 节,“MEMORY 存储引擎”,了解有关MEMORY表的更多信息。

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

19.5.1.22 mysql 系统模式的复制

mysql模式中的表进行的数据修改语句根据binlog_format的值进行复制;如果该值为MIXED,则使用基于行的格式复制这些语句。然而,通常间接更新此信息的语句,如GRANTREVOKE以及操作触发器、存储过程和视图的语句,会使用基于语句的复制方式复制到副本。

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

19.5.1.23 复制和查询优化器

如果一个语句被编写成非确定性的方式,即由查询优化器决定,那么源数据库和副本数据库上的数据可能会变得不同。(一般来说,这不是一个好的做法,即使在复制之外也是如此。)非确定性语句的例子包括使用LIMIT而没有ORDER BY子句的DELETEUPDATE语句;详细讨论请参见 Section 19.5.1.18, “Replication and LIMIT”。

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

19.5.1.24 复制和分区

只要分区表使用相同的分区方案并且结构相同,复制就支持分区表之间的复制,除非特别允许异常情况(参见 Section 19.5.1.9, “源表和副本表上定义不同的复制”)。

不同分区的表之间的复制通常不受支持。这是因为在这种情况下直接作用于分区的语句(比如ALTER TABLE ... DROP PARTITION)可能会在源表和副本表上产生不同的结果。在源表分区但副本表未分区的情况下,任何在源表副本上操作分区的语句都会在副本表上失败。当副本表分区但源表未分区时,在源表上运行直接作用于分区的语句会导致错误。为避免停止复制或在源表和副本表之间创建不一致,始终确保源表和副本表的对应复制表以相同方式分区。

原文: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,表示服务器时区与系统时区相同,则这可能导致源和副本应用不同的时区。例如,源可能在二进制日志中写入以下语句:

代码语言:javascript
复制
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副本表。但是,如果这样做,在BEGINCOMMIT块中停止副本会出现问题,因为副本会在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”。

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

代码语言:javascript
复制
SET max_join_size=1000;
INSERT INTO mytable VALUES(@@max_join_size);

这不适用于常见的顺序:

代码语言:javascript
复制
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文件中使用以下行启动服务器:

代码语言:javascript
复制
[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”,了解如何报告。

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

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

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

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

代码语言:javascript
复制
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 语法。

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

19.5.5 如何报告复制 Bug 或问题

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

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

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

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

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

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

  • 所有来自源端的二进制日志文件
  • 所有来自复制端的二进制日志文件
  • 源端在发现问题时的SHOW MASTER STATUS输出
  • 源端在发现问题时的SHOW REPLICA STATUS输出
  • 源端和复制端的错误日志

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

代码语言:javascript
复制
$> 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 的中继日志,然后在源上进行提交。在每个副本上,事务被应用,写入副本的二进制日志,并提交。源上的提交和副本上的提交都是独立的和异步的。
源接收的事务被执行,写入二进制日志,然后提交,并向客户端应用程序发送响应。二进制日志中的记录被发送到副本 1 和副本 2 的中继日志,然后在源上进行提交。在每个副本上,事务被应用,写入副本的二进制日志,并提交。源上的提交和副本上的提交都是独立的和异步的。

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

图 20.2 MySQL 半同步复制

源接收的事务被执行并写入二进制日志。二进制日志中的记录被发送到副本 1 和副本 2 的中继日志。然后源等待副本的确认。当两个副本都返回确认后,源提交事务,并向客户端应用程序发送响应。每个副本返回确认后,应用事务,将其写入二进制日志,并提交。源的提交取决于副本的确认,但副本的提交彼此独立,与源的提交独立。
源接收的事务被执行并写入二进制日志。二进制日志中的记录被发送到副本 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 将交易写入其中继日志,然后应用它,写入二进制日志,并提交它。
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 通信。
部署为互连组的五个服务器实例,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列。例如:

代码语言:javascript
复制
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状态变量。

代码语言:javascript
复制
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。
部署了五个服务器实例,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”。 ,成员 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”。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 19.4.11 延迟复制
  • 19.5 复制笔记和技巧
  • 19.5.1 复制功能和问题
  • 19.5.2 MySQL 版本之间的复制兼容性
  • 19.5.3 升级复制拓扑
  • 19.5.4 复制故障排除
  • 19.5.5 如何报告复制 Bug 或问题
  • 第二十章 组复制
  • 20.1 Group Replication 背景
  • 20.1.1 复制技术
  • 20.1.2 Group Replication 使用案例
  • 20.1.3 多主和单主模式
  • 20.1.4 组复制服务
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档