文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  跳过事务

19.1.7.3 跳过事务

如果复制由于复制事务中的事件问题而停止,您可以通过跳过副本上的失败事务来恢复复制。在跳过事务之前,请确保复制 I/O(接收器)线程和 SQL(应用器)线程已停止。

首先,您需要确定导致错误的复制事件。有关错误和最后成功应用的事务的详细信息记录在性能模式表 replication_applier_status_by_worker 中。您可以使用 mysqlbinlog 检索和显示在错误发生时间周围记录的事件。有关执行此操作的说明,请参见 第 9.5 节,“时间点(增量)恢复”。或者,您可以在副本上执行 SHOW RELAYLOG EVENTS 或在源上执行 SHOW BINLOG EVENTS

在跳过事务并重新启动副本之前,请检查以下几点

  • 导致复制停止的事务是否来自未知或不受信任的来源?如果是,请调查原因,以防存在任何安全问题,表明不应该重新启动副本。

  • 导致复制停止的事务是否需要应用到副本上?如果是,请对副本进行相应的更正并重新应用事务,或者手动协调副本上的数据。

  • 导致复制停止的事务是否需要应用到源上?如果不是,请在原始发生事务的服务器上手动撤消事务。

要跳过事务,请根据需要选择以下方法之一

要在跳过事务后重新启动复制,请执行 START REPLICA,如果副本是多源副本,则使用 FOR CHANNEL 子句。

19.1.7.3.1 跳过带有 GTID 的事务

当使用 GTID 时(gtid_modeON),即使事务内容被过滤掉,已提交事务的 GTID 也会保存在副本上。此功能可防止副本在使用 GTID 自动定位重新连接到源时检索到之前已过滤的事务。它还可以用于跳过副本上的事务,方法是在失败的事务位置提交一个空事务。

当您使用 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS 选项在复制通道上启用 GTID 分配时,这种跳过事务的方法不适合。

如果失败的事务在工作线程中生成了错误,您可以直接从 Performance Schema 表 replication_applier_status_by_worker 中的 APPLYING_TRANSACTION 字段获取其 GTID。要查看事务是什么,请在副本上执行 SHOW RELAYLOG EVENTS 或在源上执行 SHOW BINLOG EVENTS,并在输出中搜索由该 GTID 之前的那个事务。

当您评估了失败事务的任何其他适当操作(如安全注意事项)后,要跳过它,请在副本上提交一个与失败事务具有相同 GTID 的空事务。例如

SET GTID_NEXT='aaa-bbb-ccc-ddd:N';
BEGIN;
COMMIT;
SET GTID_NEXT='AUTOMATIC';

副本上存在此空事务意味着,当您发出 START REPLICA 语句来重新启动复制时,副本使用自动跳过功能来忽略失败的事务,因为它看到具有该 GTID 的事务已应用。如果副本是多源副本,则在提交空事务时不需要指定通道名称,但在发出 START REPLICA 时需要指定通道名称。

请注意,如果在此副本上使用了二进制日志记录,如果副本将来成为源或主服务器,空事务将进入复制流。如果您需要避免这种情况,请考虑刷新和清除副本的二进制日志,例如

FLUSH LOGS;
PURGE BINARY LOGS TO 'binlog.000146';

空事务的 GTID 会持久化,但事务本身会通过清除二进制日志文件而被删除。

19.1.7.3.2 跳过没有 GTID 的事务

要跳过 GTID 未使用或正在逐步引入时的失败事务(gtid_modeOFFOFF_PERMISSIVEON_PERMISSIVE),您可以通过发出 SET GLOBAL sql_replica_skip_counter 来跳过指定数量的事件。或者,您可以通过发出 CHANGE REPLICATION SOURCE TO 语句来向前移动源二进制日志位置,跳过事件或事件。

当您使用 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS 选项在复制通道上启用 GTID 分配时,这些方法也适用。

当您使用这些方法时,重要的是要了解,您并不一定会跳过一个完整的事务,正如之前描述的基于 GTID 的方法总是那样。这些基于非 GTID 的方法并不了解事务本身,而是对事件进行操作。二进制日志被组织为一系列称为事件组的组,每个事件组包含一系列事件。

  • 对于事务表,一个事件组对应于一个事务。

  • 对于非事务表,一个事件组对应于一个 SQL 语句。

一个事务可以包含对事务表和非事务表的更改。

当您使用 SET GLOBAL sql_replica_skip_counter 语句来跳过事件,并且结果位置位于事件组的中间时,副本会继续跳过事件,直到到达该组的末尾。然后从下一个事件组开始执行。 CHANGE REPLICATION SOURCE TO 语句没有此功能,因此您必须小心地识别正确的位置,以便在事件组的开头重新启动复制。但是,使用 CHANGE REPLICATION SOURCE TO 意味着您不必像使用 SET GLOBAL sql_replica_skip_counter 那样计算需要跳过的事件,而是可以只指定要重新启动的位置。

19.1.7.3.2.1 使用 SET GLOBAL sql_replica_skip_counter 跳过事务

当您评估了失败事务的任何其他适当操作(如安全注意事项)后,请计算需要跳过的事件数量。一个事件通常对应于二进制日志中的一个 SQL 语句,但请注意,使用 AUTO_INCREMENTLAST_INSERT_ID() 的语句在二进制日志中算作两个事件。当使用二进制日志事务压缩时,压缩的事务有效负载(Transaction_payload_event)被计为一个计数器值,因此它内部的所有事件都作为一个单元被跳过。

如果要跳过整个事务,您可以计算到事务末尾的事件,或者只跳过相关事件组。请记住,使用 SET GLOBAL sql_replica_skip_counter,副本将继续跳过到事件组的末尾。请确保不要跳过太多,进入下一个事件组或事务,以免它也被跳过。

按如下所示发出 SET 语句,其中 N 是要跳过的源事件数

SET GLOBAL sql_replica_skip_counter = N

如果设置了 gtid_mode=ON,或者复制 I/O(接收器)和 SQL(应用器)线程正在运行,则无法发出此语句。

SET GLOBAL sql_replica_skip_counter 语句没有立即生效。当您在发出此 SET 语句后的下一次发出 START REPLICA 语句时,系统变量 sql_replica_skip_counter 的新值将被应用,并且事件将被跳过。该 START REPLICA 语句还会自动将系统变量的值重置为 0。如果副本是多源副本,则在发出该 START REPLICA 语句时,需要 FOR CHANNEL 子句。确保您指定了正确的通道名称,否则会跳过错误通道上的事件。

19.1.7.3.2.2 使用 CHANGE REPLICATION SOURCE TO 跳过事务

当您评估了失败事务的任何其他适当操作(如安全注意事项)后,请确定源二进制日志中表示适合重新启动复制的位置的坐标(文件和位置)。这可以是导致问题的事件之后的事件组的开头,或下一个事务的开头。复制 I/O(接收器)线程在下一次启动时从这些坐标开始读取源数据,跳过失败的事件。确保您已准确地识别位置,因为此语句不会考虑事件组。

按如下所示发出 CHANGE REPLICATION SOURCE TO 语句,其中 source_log_name 是包含重新启动位置的二进制日志文件,source_log_pos 是表示二进制日志文件中所述的重新启动位置的数字

CHANGE REPLICATION SOURCE TO SOURCE_LOG_FILE='source_log_name', SOURCE_LOG_POS=source_log_pos;

如果副本是多源副本,则必须使用 FOR CHANNEL 子句在 CHANGE REPLICATION SOURCE TO 语句中指定相应的通道。

如果 SOURCE_AUTO_POSITION1,或者复制 I/O(接收器)和 SQL(应用器)线程正在运行,则无法发出此语句。如果您需要在 SOURCE_AUTO_POSITION=1 时使用此跳过事务的方法,则可以在发出语句时将设置更改为 SOURCE_AUTO_POSITION=0,然后在之后将其更改回来。例如

CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=0, SOURCE_LOG_FILE='binlog.000145', SOURCE_LOG_POS=235;
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=1;