文档主页
MySQL 9.0 参考手册
相关文档 下载此手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

19.1.7.3 跳过事务

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

首先,您需要确定导致错误的复制事件。错误的详细信息以及最后成功应用的事务记录在 Performance Schema 表 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 自动定位重新连接到源时检索之前过滤的事务。它还可以用于跳过副本上的事务,方法是在发生故障的事务位置提交一个空事务。

当您使用 CHANGE REPLICATION SOURCE TO 语句的 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS 选项在复制通道上启用 GTID 分配时,此跳过事务的方法不适用。

如果发生故障的事务在工作线程中生成错误,您可以直接从 Performance Schema 表 replication_applier_status_by_workerAPPLYING_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 时(gtid_modeOFFOFF_PERMISSIVEON_PERMISSIVE)),您可以通过发出 SET GLOBAL sql_replica_skip_counter 跳过指定数量的事件。或者,您可以通过发出 CHANGE REPLICATION SOURCE TO 语句向前移动源二进制日志位置来跳过一个或多个事件。

当您使用 CHANGE REPLICATION SOURCE TO 语句的 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS 选项在复制通道上启用 GTID 分配时,这些方法也适用。

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

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

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

虽然单个事务可能包含对事务表和非事务表的更改,但对这类事务的支持已弃用,您应该预期它将在 MySQL 的未来版本中被删除。请参阅 第 19.5.1.36 节,“复制和事务”。有关此弃用的一些原因,请参阅 第 19.1.3.7 节,“使用 GTID 的复制限制”

当您使用 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;

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

如果 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;