Documentation Home

16.4.1.32 复制和事务不一致

根据您的复制配置,从中继日志执行的事务序列可能会出现不一致。本节说明如何避免不一致并解决它们引起的任何问题。

可能存在以下类型的不一致:

  • 半应用事务。更新非事务表的事务应用了部分但不是全部更改。

  • 差距。间隙是尚未完全应用的事务,即使序列中稍后的某些事务已被应用。只有在使用多线程副本时才会出现间隙。为避免出现间隙,设置 slave_preserve_commit_order=1,这需要 slave_parallel_type=LOGICAL_CLOCK,并且log-binlog-slave-updates启用了。请注意, slave_preserve_commit_order=1 这不会保留非事务性 DML 更新的顺序,因此这些更新可能会在中继日志中先于它们之前的事务提交,这可能会导致间隙。

  • 源二进制日志位置滞后。即使没有差距,也有可能 Exec_master_log_pos应用了之后的交易。也就是说,到 point 为止的所有交易N 都已应用,并且没有应用之后的交易 N,但 Exec_master_log_pos其值小于N。在这种情况下, Exec_master_log_pos是申请的交易的低水位线,落后于最近申请的交易的位置。这只会发生在多线程副本上。启用 slave_preserve_commit_order 不会阻止源二进制日志位置滞后。

以下场景与半应用事务、间隙和源二进制日志位置滞后的存在有关:

  1. 当复制线程正在运行时,可能存在间隙和半应用事务。

  2. mysqld关闭。干净和不干净的关闭都会中止正在进行的事务,并可能留下间隙和半应用事务。

  3. KILL复制线程(使用单线程副本时的 SQL 线程,使用多线程副本时的协调器线程)。这会中止正在进行的交易,并可能留下空白和半应用交易。

  4. 应用程序线程错误。这可能会留下空白。如果错误出现在混合事务中,则该事务应用了一半。使用多线程副本时,未收到错误的工作人员会完成其队列,因此停止所有线程可能需要一些时间。

  5. STOP SLAVE使用多线程副本时。发出后 STOP SLAVE,副本等待任何间隙被填充,然后更新 Exec_master_log_pos。这确保它永远不会留下间隙或源二进制日志位置滞后,除非上述任何情况适用,换句话说,在 STOP SLAVE完成之前,要么发生错误,要么另一个线程问题 KILL,或者服务器重新启动。在这些情况下,STOP SLAVE 返回成功。

  6. 如果中继日志中的最后一个事务只被接收到一半,并且多线程副本协调器已经开始将事务调度给一个工作人员,那么 STOP SLAVE最多等待 60 秒以接收事务。超时后,协调器放弃并中止事务。如果交易是混合的,则可能会半途而废。

  7. STOP SLAVE当正在进行的事务仅更新事务表时,在这种情况下它会回滚并STOP SLAVE立即停止。如果正在进行的事务是混合的,则STOP SLAVE最多等待 60 秒以便事务完成。超时后,它会中止事务,因此它可能只完成了一半。

全局变量 rpl_stop_slave_timeout与停止复制线程的过程无关。它只会使发出问题的客户端STOP SLAVE返回到客户端,但复制线程会继续尝试停止。

如果复制通道存在间隙,则会产生以下后果:

  1. 副本数据库处于源上可能从未存在过的状态。

  2. Exec_master_log_pos中 的字段SHOW SLAVE STATUS只是一个 低水位线。换句话说,保证在该位置之前出现的事务已提交,但在该位置之后的事务可能已提交或未提交。

  3. CHANGE MASTER TO该通道的语句因错误而失败,除非应用程序线程正在运行并且该CHANGE MASTER TO语句仅设置接收器选项。

  4. 如果mysqld以 启动 --relay-log-recovery,则不会对该通道进行任何恢复,并打印一条警告。

  5. 如果mysqldump与 一起使用 --dump-slave,它不会记录间隙的存在;因此它打印 CHANGE MASTER TORELAY_LOG_POS设置为 中的低水位标记位置 Exec_master_log_pos

    在另一台服务器上应用转储并启动复制线程后,再次复制该位置之后出现的事务。请注意,如果启用了 GTID,这是无害的(但是,在这种情况下,不建议使用 --dump-slave)。

如果复制通道有源二进制日志位置滞后但没有间隙,则上述情况 2 到 5 适用,但情况 1 不适用。

源二进制日志位置信息以二进制格式保存在内表中 mysql.slave_worker_infoSTART SLAVE [SQL_THREAD]始终查阅此信息,以便它仅应用正确的交易。slave_parallel_workers即使在 之前已更改为 0 START SLAVE,并且即使START SLAVEUNTIL子句 一起使用,这仍然是正确的。START SLAVE UNTIL SQL_AFTER_MTS_GAPS仅应用所需数量的交易以填补空白。If START SLAVEUNTIL告诉它在消耗完所有间隙之前停止的子句一起使用,然后它会留下剩余的间隙。

警告

RESET SLAVE删除中继日志并重置复制位置。因此 RESET SLAVE,在具有间隙的副本上发布意味着副本丢失了关于间隙的任何信息,而不纠正间隙。

当使用基于 GTID 的复制时,从 MySQL 5.7.28 开始,多线程副本首先检查是否 MASTER_AUTO_POSITION设置为 ON,如果是,则省略计算应该跳过或不跳过的事务的步骤。在那种情况下,恢复过程不需要旧的中继日志。