Documentation Home

16.1.7.3 跳过交易

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

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

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

  • 停止从未知或不受信任源复制的事务?如果是这样,请调查原因,以防有任何安全考虑表明不应重新启动副本。

  • 停止复制的事务是否需要应用于副本?如果是这样,要么进行适当的更正并重新应用事务,要么手动协调副本上的数据。

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

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

要在跳过事务后重新启动复制,请发出 START SLAVE带有 FOR CHANNEL如果副本是多源副本的子句的问题。

16.1.7.3.1 使用 GTID 跳过事务

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

如果失败的事务在工作线程中产生错误,您可以直接从 APPLYING_TRANSACTIONPerformance Schema 表中的字段 获取其 GTID replication_applier_status_by_worker。要查看事务是什么,请 SHOW RELAYLOG EVENTS在副本或SHOW BINLOG EVENTS源上发出,并在输出中搜索以该 GTID 开头的事务。

当您已评估失败事务以执行前面所述的任何其他适当操作(例如安全考虑)时,要跳过它,请在与失败事务具有相同 GTID 的副本上提交一个空事务。例如:

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

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

请注意,如果此副本正在使用二进制日志记录,则如果副本将来成为源或主副本,则空事务将进入复制流。如果您需要避免这种可能性,请考虑刷新和清除副本的二进制日志,如本例所示:

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

保留空事务的 GTID,但通过清除二进制日志文件删除事务本身。

16.1.7.3.2 跳过没有 GTID 的事务

要在 GTID 未使用或正在分阶段使用(gtid_modeis OFFOFF_PERMISSIVEON_PERMISSIVE)时跳过失败的事务,您可以通过发出SET GLOBAL sql_slave_skip_counter语句来跳过指定数量的事件。CHANGE MASTER TO或者,您可以通过发出语句将源的二进制日志位置向前移动 来跳过一个或多个事件 。

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

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

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

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

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

16.1.7.3.2.1 跳过交易SET GLOBAL sql_slave_skip_counter

当您评估了任何其他适当操作(例如安全考虑)的失败事务后,请计算您需要跳过的事件数。一个事件通常对应二进制日志中的一条 SQL 语句,但请注意,在二进制日志中使用AUTO_INCREMENTLAST_INSERT_ID()计为两个事件的语句。

如果想跳过完整的事务,可以统计到事务结束的事件,也可以直接跳过相关的事件组。请记住,对于 SET GLOBAL sql_slave_skip_counter,副本会继续跳到事件组的末尾。确保您不要跳得太远而进入下一个事件组或事务,因为这会导致它也被跳过。

发出SET如下语句,其中 N要跳过的来自源的事件数:

SET GLOBAL sql_slave_skip_counter = N

gtid_mode=ON如果已设置,或者副本线程正在运行,则 无法发出此语句 。

SET GLOBAL sql_slave_skip_counter 声明没有立即生效。当您在该 START SLAVE语句之后发出下一次SET语句时,将应用系统变量的新值 sql_slave_skip_counter,并跳过事件。该 START SLAVE语句还会自动将系统变量的值设置回 0。如果副本是多源副本,则当您发出该START SLAVE语句时,该FOR CHANNEL子句是必需的。确保命名正确的频道,否则事件会在错误的频道上被跳过。

16.1.7.3.2.2 跳过事务CHANGE MASTER TO

当您评估失败的事务以执行前面所述的任何其他适当操作(例如安全考虑)时,请在源的二进制日志中确定坐标(文件和位置),这些坐标代表重新启动复制的合适位置。这可以是导致问题的事件之后的事件组的开始,也可以是下一个事务的开始。复制 I/O 线程在下次线程启动时从这些坐标处的源开始读取,跳过失败事件。请确保您已准确识别位置,因为此声明未将事件组考虑在内。

发出CHANGE MASTER TO 如下语句,其中 source_log_name是包含重启位置的二进制日志文件,是二进制日志文件中表示重启位置 source_log_pos的数字:

CHANGE MASTER TO MASTER_LOG_FILE='source_log_name', MASTER_LOG_POS=source_log_pos;

如果副本是多源副本,则必须使用 FOR CHANNEL子句在语句中命名适当的通道CHANGE MASTER TO

MASTER_AUTO_POSITION=1如果已设置或复制线程正在运行,则 无法发出此语句 。正常设置时如果需要使用这种跳过事务的方法 MASTER_AUTO_POSITION=1,可以在发出语句时将设置改为 MASTER_AUTO_POSITION=0,之后再改回来。例如:

CHANGE MASTER TO MASTER_AUTO_POSITION=0, MASTER_LOG_FILE='binlog.000145', MASTER_LOG_POS=235;
CHANGE MASTER TO MASTER_AUTO_POSITION=1;