MySQL8 中文参考(八十)(3)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: MySQL8 中文参考(八十)

MySQL8 中文参考(八十)(2)https://developer.aliyun.com/article/1565888


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

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


MySQL8 中文参考(八十)(4)https://developer.aliyun.com/article/1565890

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
关系型数据库 MySQL Unix
MySQL8 中文参考(二十三)(3)
MySQL8 中文参考(二十三)
54 4
|
5月前
|
存储 缓存 关系型数据库
MySQL8 中文参考(二十一)(5)
MySQL8 中文参考(二十一)
82 3
|
5月前
|
存储 监控 Java
MySQL8 中文参考(二十一)(4)
MySQL8 中文参考(二十一)
140 3
|
5月前
|
存储 安全 关系型数据库
MySQL8 中文参考(二十一)(1)
MySQL8 中文参考(二十一)
49 3
|
5月前
|
存储 关系型数据库 MySQL
MySQL8 中文参考(二十一)(3)
MySQL8 中文参考(二十一)
72 2
|
5月前
|
关系型数据库 MySQL Unix
MySQL8 中文参考(二十一)(2)
MySQL8 中文参考(二十一)
75 2
|
5月前
|
关系型数据库 MySQL 数据安全/隐私保护
MySQL8 中文参考(二十五)(5)
MySQL8 中文参考(二十五)
49 2
|
5月前
|
存储 关系型数据库 MySQL
MySQL8 中文参考(二十四)(1)
MySQL8 中文参考(二十四)
56 2
|
5月前
|
NoSQL 关系型数据库 MySQL
MySQL8 中文参考(二十三)(2)
MySQL8 中文参考(二十三)
62 2
|
5月前
|
存储 关系型数据库 MySQL
MySQL8 中文参考(二十三)(1)
MySQL8 中文参考(二十三)
37 2