16.4.1.32 复制和事务不一致

从中继日志执行的事务 Sequences 不一致可能会发生,具体取决于您的复制配置。本节说明如何避免不一致并解决它们引起的任何问题。

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

  • 半申请 Transaction。更新非事务处理 table 的事务已应用了部分但不是全部更改。

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

  • 源二进制日志位置滞后。即使没有间隙,也有可能应用了Exec_master_log_pos之后的事务。也就是说,直到N点为止的所有事务都已应用,并且未应用N之后的事务,但是Exec_master_log_pos的值小于N。在这种情况下,Exec_master_log_pos是所应用事务的“低水位标记”,并且落后于最近应用的事务的位置。这只能在多线程副本上发生。启用slave_preserve_commit_order不会防止源二进制日志位置滞后。

以下情况与半应用的事务,差距和源二进制日志位置滞后的存在有关:

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

  • mysqld关闭。干净和不干净的关闭都会中止正在进行的事务,并且可能会留下空白和半应用的事务。

  • KILL个复制线程(使用单线程副本时为 SQL 线程,使用多线程副本时为协调器线程)。这将中止正在进行的 Transaction,并可能留下缺口和半申请的 Transaction。

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

  • 使用多线程副本时为STOP SLAVE。发出STOP SLAVE之后,副本服务器 await 所有空白被填充,然后更新Exec_master_log_pos。这样可以确保它永远不会留下间隙或源二进制日志位置滞后,除非以上任何情况都适用,换句话说,在STOP SLAVE完成之前,要么发生错误,要么另一个线程发出KILL,否则服务器将重新启动。在这些情况下,STOP SLAVE成功返回。

  • 如果中继日志中的最后一个事务仅被接收一半,并且多线程副本协调器已开始将事务调度给工作程序,则STOP SLAVE最多 await60 秒以接收事务。超时后,协调器放弃并中止事务。如果 Transaction 混合,则可能会完成一半。

  • 使用单线程副本时为STOP SLAVE。如果正在进行的事务仅更新事务 table,则会回滚它,并且STOP SLAVE立即停止。如果正在进行的事务混合在一起,则STOP SLAVE最多 await60 秒以完成事务。此超时后,它将中止事务,因此它可能会保留一半。

全局变量rpl_stop_slave_timeout与停止复制线程的过程无关。它只会使发出STOP SLAVE的 Client 端返回到 Client 端,但是复制线程 continue 尝试停止。

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

  • 副本数据库处于可能永远不会在源上存在的状态。

  • 显示从站状态中的Exec_master_log_pos字段仅是“低水位标记”。换句话说,保证在该头寸之前出现的 Transaction 已被保证已落实,但在该头寸之后的 Transaction 可能已承诺或未承诺。

  • 除非该应用程序线程正在运行并且更改为主语句仅设置接收器选项,否则该通道的更改为主语句将失败并显示错误。

  • 如果mysqld--relay-log-recovery开头,则该通道不会恢复,并显示警告。

  • 如果mysqldump--dump-slave一起使用,则不会记录间隙的存在;因此它会打印更改为主并将RELAY_LOG_POS设置为Exec_master_log_pos中的“低水印”位置。

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

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

源二进制日志位置信息以二进制格式保存在内部 tablemysql.slave_worker_info中。 开始从[SQL_THREAD]始终会查询此信息,以便仅应用正确的 Transaction。即使在START SLAVE之前将slave_parallel_workers更改为 0,甚至将START SLAVEUNTIL子句一起使用,也是如此。 从开始直到 SQL_AFTER_MTS_GAPS仅根据需要应用尽可能多的事务以填补空白。如果START SLAVEUNTIL子句一起使用,告诉它在耗尽所有间隙之前停止运行,则它将留下剩余的间隙。

Warning

RESET SLAVE删除中继日志并重置复制位置。因此,在具有间隙的副本上发出RESET SLAVE意味着该副本会丢失有关间隙的任何信息,而无需校正间隙。