MySQL8 中文参考(八十)(3)https://developer.aliyun.com/article/1565889
19.5.1.35 复制和事务
在同一事务中混合事务和非事务语句。 一般来说,在复制环境中,应避免更新既有事务表又有非事务表的事务。还应避免使用任何访问既有事务(或临时)表又访问非事务表并写入其中的语句。
服务器使用以下规则进行二进制日志记录:
- 如果事务中的初始语句是非事务的,则立即写入二进制日志。事务中的其余语句被缓存,直到事务提交时才写入二进制日志。(如果事务回滚,则仅当它们进行不可回滚的非事务更改时,缓存的语句才会写入二进制日志。否则,它们将被丢弃。)
- 对于基于语句的日志记录,非事务语句的记录受
binlog_direct_non_transactional_updates系统变量的影响。当此变量为OFF(默认值)时,记录如上所述。当此变量为ON时,对于事务中发生的任何非事务语句,立即记录(不仅仅是初始的非事务语句)。其他语句被保留在事务缓存中,并在事务提交时记录。binlog_direct_non_transactional_updates对于行格式或混合格式的二进制日志记录没有影响。
事务、非事务和混合语句。 为了应用这些规则,服务器认为一个语句是非事务的,如果它只改变非事务表,而认为是事务的,如果它只改变事务表。一个引用了非事务表和事务表并更新任何涉及的表的语句被视为“混合”语句。混合语句,像事务语句一样,在事务提交时被缓存和记录。
更新事务表的混合语句,如果该语句还执行以下任一操作,则被视为不安全:
- 更新或读取临时表
- 读取非事务表且事务隔离级别低于 REPEATABLE_READ
在事务中更新事务表后的混合语句,如果执行以下任一操作,则被视为不安全:
- 更新任何表并从任何临时表读取
- 更新非事务表且
binlog_direct_non_transactional_updates为关闭状态
更多信息,请参见 Section 19.2.1.3, “Determination of Safe and Unsafe Statements in Binary Logging”.
注意
混合语句与混合二进制日志格式无关。
在事务混合更新事务和非事务表的情况下,二进制日志中语句的顺序是正确的,即使在ROLLBACK的情况下,所有需要的语句也会被写入二进制日志。然而,当第二个连接在第一个连接事务完成之前更新非事务表时,语句可能会因为第二个连接的更新立即写入,而不考虑第一个连接正在执行的事务状态,导致日志顺序混乱。
在源和副本上使用不同的存储引擎。 可以在源上使用非事务表复制事务表到副本上。例如,可以将InnoDB源表复制为MyISAM副本表。但是,如果这样做,在BEGIN … COMMIT块中停止副本会出现问题,因为副本会在BEGIN块的开头重新启动。
将MyISAM表上的事务复制到副本上的事务表,例如使用InnoDB存储引擎的表,也是安全的。在这种情况下,在源上发出的AUTOCOMMIT=1语句会被复制,从而在副本上强制执行AUTOCOMMIT模式。
当副本的存储引擎类型为非事务时,应避免在源上混合更新事务和非事务表的事务,因为它们可能导致源事务表和副本非事务表之间的数据不一致。也就是说,这样的事务可能导致源存储引擎特定行为,可能导致复制失去同步。MySQL 不会对此发出警告,因此在将源上的事务表复制到副本上的非事务表时,应格外小心。
更改事务中的二进制日志格式。 只要事务正在进行中,binlog_format和binlog_checksum系统变量是只读的。
每个事务(包括autocommit事务)都被记录在二进制日志中,就好像它以BEGIN语句开始,以COMMIT或ROLLBACK语句结束。即使是影响使用非事务性存储引擎(如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)
触发器可以针对不同的触发事件组合(INSERT、UPDATE、DELETE)和动作时间(BEFORE、AFTER)拥有触发器,并且允许多个触发器。
为简洁起见,“多个触发器”在这里是“具有相同触发事件和动作时间的多个触发器”的简称。
升级。 早于 MySQL 5.7 版本不支持多个触发器。如果在使用早于 MySQL 5.7 的版本的复制拓扑中升级服务器,请先升级副本,然后再升级源。如果升级后的复制源服务器仍有使用不支持多个触发器的 MySQL 版本的旧副本,那么如果在源上为已经具有相同触发事件和动作时间的触发器的表创建触发器,则在这些副本上会出现错误。
降级。 如果将支持多个触发器的服务器降级到不支持多个触发器的旧版本,降级会产生以下影响:
- 对于具有触发器的每个表,所有触发器定义都在该表的
.TRG文件中。然而,如果存在具有相同触发事件和动作时间的多个触发器,当触发事件发生时,服务器只会执行其中一个。有关.TRG文件的信息,请参阅 MySQL 服务器 Doxygen 文档中的表触发器存储部分,网址为dev.mysql.com/doc/index-other.html。 - 如果在降级后添加或删除表的触发器,则服务器会重写表的
.TRG文件。重写后的文件仅保留每个触发器事件和动作时间组合中的一个触发器;其他触发器将丢失。
为避免这些问题,在降级之前修改您的触发器。对于每个表,如果每个触发器事件和动作时间组合中有多个触发器,请将每组触发器转换为单个触发器,方法如下:
- 对于每个触发器,创建一个包含触发器中所有代码的存储过程。使用
NEW和OLD访问的值可以通过参数传递给存储过程。如果触发器需要代码中的单个结果值,可以将代码放入存储函数中,并让函数返回该值。如果触发器需要代码中的多个结果值,可以将代码放入存储过程中,并使用OUT参数返回这些值。 - 删除表的所有触发器。
- 为表创建一个新的触发器,调用刚刚创建的存储过程。因此,这个触发器的效果与它替代的多个触发器相同。
原文:
dev.mysql.com/doc/refman/8.0/en/replication-features-truncate.html
19.5.1.37 复制和 TRUNCATE TABLE
TRUNCATE TABLE通常被视为 DML 语句,因此在二进制日志记录模式为ROW或MIXED时,预计会使用基于行的格式进行记录和复制。然而,在以STATEMENT或MIXED模式记录或复制时,当事务隔离级别为READ COMMITTED或READ 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_incrementauto_increment_offsetcharacter_set_clientcharacter_set_connectioncharacter_set_databasecharacter_set_servercollation_connectioncollation_databasecollation_serverforeign_key_checksidentitylast_insert_idlc_time_namespseudo_thread_idsql_auto_is_nulltime_zonetimestampunique_checks
当使用MIXED模式时,前述列表中的变量在会话范围内使用时会导致从基于语句的日志记录切换到基于行的日志记录。请参阅 Section 7.4.4.3, “Mixed Binary Logging Format”。
sql_mode也会被复制,除了NO_DIR_IN_CREATE模式;复制品始终保留自己的NO_DIR_IN_CREATE值,而不管源上对其进行了何种更改。这对所有复制格式都适用。
然而,当mysqlbinlog解析SET @@sql_mode = *mode*语句时,包括NO_DIR_IN_CREATE在内的完整*mode*值将传递给接收服务器。因此,在使用STATEMENT模式时,此类语句的复制可能不安全。
default_storage_engine系统变量不会被复制,无论日志记录模式如何;这旨在促进不同存储引擎之间的复制。
read_only 系统变量不会被复制。此外,启用此变量在不同的 MySQL 版本中对临时表、表锁定和 SET PASSWORD 语句产生不同的影响。
max_heap_table_size 系统变量不会被复制。在源上增加此变量的值而在副本上未这样做最终可能导致在副本上执行 MEMORY 表的 INSERT 语句时出现 Table is full 错误,因为源上的表被允许比副本上的表更大。有关更多信息,请参见 Section 19.5.1.21, “Replication and MEMORY Tables”。
在基于语句的复制中,当在更新表的语句中使用会话变量时,会话变量不会被正确复制。例如,以下语句序列在源和副本上不会插入相同的数据:
SET max_join_size=1000; INSERT INTO mytable VALUES(@@max_join_size);
这不适用于常见的顺序:
SET time_zone=...; INSERT INTO mytable VALUES(CONVERT_TZ(..., ..., @@time_zone));
当使用基于行的复制时,会话变量的复制不是问题,此时会话变量始终安全地被复制。参见 Section 19.2.1, “Replication Formats”。
以下会话变量被写入二进制日志,并在解析二进制日志时由副本进行尊重,无论日志格式如何:
sql_modeforeign_key_checksunique_checkscharacter_set_clientcollation_connectioncollation_databasecollation_serversql_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 升级复制拓扑
当您升级参与复制拓扑的服务器时,您需要考虑每个服务器在拓扑中的角色,并注意与复制相关的问题。有关升级 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_TABLES或STRICT_ALL_TABLES)影响操作的更改可能导致升级后副本的复制失败。如果使用基于语句的日志记录(binlog_format=STATEMENT),如果副本在源之前升级,源执行的语句在那里成功,但在副本上可能失败,从而导致复制停止。为了解决这个问题,停止源上的所有新语句,并等待副本赶上,然后升级副本。或者,如果无法停止新语句,暂时在源上切换到基于行的日志记录(binlog_format=ROW),并等待所有副本处理到达此更改点之前产生的所有二进制日志,然后升级副本。
默认字符集从latin1更改为utf8mb4在 MySQL 8.0 中。在复制设置中,当从 MySQL 5.7 升级到 8.0 时,建议在升级之前将默认字符集更改回 MySQL 5.7 中使用的字符集。升级完成后,可以将默认字符集更改为utf8mb4。假设之前使用了默认设置,保留它们的一种方法是在my.cnf文件中使用以下行启动服务器:
[mysqld] character_set_server=latin1 collation_server=latin1_swedish_ci
标准升级程序
要升级复制拓扑,请按照第三章“升级 MySQL”中的说明为每个单独的 MySQL 服务器实例执行此整体过程:
- 首先升级副本。在每个副本实例上:
- 执行第 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 REPLICA或START SLAVE语句重新启动复制。
- 当所有副本都已升级时,按照相同步骤升级和重新启动源服务器,但不包括
START REPLICA或START SLAVE语句。如果您对基于行的日志记录或默认字符集进行了临时更改,现在可以恢复更改。
使用表修复或重建的升级过程
在从一个 MySQL 系列移动到下一个系列时,某些升级可能需要您删除并重新创建数据库对象。例如,排序规则更改可能需要重建表索引。如果需要这样的操作,则在第 3.5 节“MySQL 8.0 中的更改”中有详细说明。最安全的做法是在副本和源上分别执行这些操作,并禁用从源到副本的这些操作的复制。为此,请使用以下过程:
- 停止所有复制实例并升级二进制文件或软件包。使用
--skip-slave-start选项或从 MySQL 8.0.24 开始,使用skip_slave_start系统变量重新启动它们,以便它们不连接到源。执行任何需要重新创建数据库对象的表修复或重建操作,例如使用REPAIR TABLE或ALTER TABLE,或者转储和重新加载表或触发器。 - 在源上禁用二进制日志。要在不重新启动源的情况下执行此操作,请执行
SET sql_log_bin = OFF语句。或者,停止源并使用--skip-log-bin选项重新启动它。如果重新启动源,则可能还希望禁止客户端连接。例如,如果所有客户端都使用 TCP/IP 连接,请在重新启动源时启用skip_networking系统变量。 - 禁用二进制日志后,执行任何需要重新创建数据库对象的表修复或重建操作。在此步骤中必须禁用二进制日志,以防止这些操作被记录并稍后发送到复制实例。
- 在源上重新启用二进制日志。如果之前将
sql_log_bin设置为OFF,则执行SET sql_log_bin = ON语句。如果重新启动源以禁用二进制日志,请在不使用--skip-log-bin的情况下重新启动,并且不启用skip_networking系统变量,以便客户端和复制实例可以连接。 - 重新启动复制实例,这次不使用
--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_Running和Replica_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 的网络端口未被过滤。
- 通过使用
ping或traceroute/tracert到达主机来检查是否可以访问源。
- 如果副本以前正在运行但已停止,则原因通常是在源上成功运行的某个语句在副本上失败。如果您已经正确地对源进行了快照,并且从未在复制线程之外修改副本上的数据,则不应该发生这种情况。如果副本意外停止,则是一个错误,或者您遇到了 Section 19.5.1, “Replication Features and Issues”中描述的已知复制限制之一。如果是错误,请参阅 Section 19.5.5, “How to Report Replication Bugs or Problems”,了解如何报告。
- 如果在源上成功运行的语句在副本上拒绝运行,请尝试以下步骤,如果不可行,则无法通过删除副本的数据库并从源复制新快照进行完整数据库重新同步:
- 确定副本上受影响的表是否与源表不同。尝试理解是如何发生的。然后使副本的表与源的表相同,并运行
START REPLICA。 - 如果前面的步骤不起作用或不适用,请尝试理解是否可以安全地手动进行更新(如果需要),然后忽略源的下一个语句。
- 如果您决定副本可以跳过源的下一个语句,请发出以下语句:
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_INCREMENT或LAST_INSERT_ID(),则*N*的值应为 1。否则,该值应为 2。对于使用AUTO_INCREMENT或LAST_INSERT_ID()的语句使用值 2 的原因是它们在源的二进制日志中占据两个事件。
参见 SET GLOBAL sql_slave_skip_counter 语法。 - 如果您确定副本最初与源完全同步,并且没有人在复制线程之外更新涉及的表,则差异可能是由错误引起的。如果您正在运行最新版本的 MySQL,请报告问题。如果您正在运行旧版本,请尝试升级到最新的生产版本以确定问题是否仍然存在。
19.5.5 如何报告复制 Bug 或问题
当确定没有用户错误涉及,并且复制仍然无法正常工作或不稳定时,是时候向我们发送 bug 报告了。我们需要尽可能多地从您那里获取信息以便追踪 bug。请花些时间和精力准备一个好的 bug 报告。
如果您有一个可重现的测试用例来演示 bug,请按照第 1.5 节“如何报告 Bug 或问题”中给出的说明将其输入到我们的 bug 数据库中。如果您遇到“幻影”问题(即您无法随意复制的问题),请使用以下步骤:
- 验证没有用户错误涉及。例如,如果您在复制线程之外更新复制端,数据将不同步,更新时可能会出现唯一键冲突。在这种情况下,复制线程会停止并等待您手动清理表以将其带入同步状态。这不是一个复制问题。这是外部干扰导致复制失败的问题。
- 确保复制端正在运行并启用了二进制日志记录(
log_bin系统变量),并启用了--log-slave-updates选项,这会导致复制端将从源端接收的更新记录到自己的二进制日志中。这些设置是默认设置。 - 在重置复制状态之前,请保存所有证据。如果我们没有信息或只有零碎的信息,那么追踪问题将变得困难或不可能。您应该收集的证据包括:
- 所有来自源端的二进制日志文件
- 所有来自复制端的二进制日志文件
- 源端在发现问题时的
SHOW MASTER STATUS输出 - 源端在发现问题时的
SHOW REPLICA STATUS输出 - 源端和复制端的错误日志
- 使用mysqlbinlog来检查二进制日志。以下内容应有助于找到问题陈述。*
log_file和log_pos*是SHOW REPLICA STATUS中的Master_Log_File和Read_Master_Log_Pos值。
$> mysqlbinlog --start-position=*log_pos* *log_file* | head
在收集了问题的证据之后,首先尝试将其作为一个独立的测试用例进行隔离。然后,按照第 1.5 节,“如何报告错误或问题”中的说明,尽可能多地输入问题信息到我们的错误数据库中。
MySQL8 中文参考(八十)(5)https://developer.aliyun.com/article/1565891