暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【ACDU翻译】MySQL 17.5.1.34 复制和事务不一致

原创 由迪 2022-11-14
256

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

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

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

  • 差距。当给定有序的事务序列时,当在该序列中较晚的事务被应用在该序列中在前的某个其他事务之前,就会出现外部化事务集中的间隙。只有在使用多线程副本时才会出现间隙。

    为避免在多线程副本上出现间隙,请设置 replica_preserve_commit_order=ON (从 MySQL 8.0.26 开始)或 slave_preserve_commit_order=ON (在 MySQL 8.0.26 之前)。从 MySQL 8.0.27 开始,此设置是默认设置,因为从该版本默认所有副本都是多线程的。

    直到 MySQL 8.0.18(包括 MySQL 8.0.18),保留提交顺序需要同时启用二进制日志记录(log_bin)和副本更新日志记录(log_replica_updateslog_slave_updates),这是 MySQL 8.0 的默认设置。从 MySQL 8.0.19 开始,副本不需要二进制日志记录和副本更新日志记录来设置 replica_preserve_commit_order=ON or slave_preserve_commit_order=ON,并且可以根据需要禁用。

    在所有版本中,设置 replica_preserve_commit_order=ONslave_preserve_commit_order=ON 要求 replica_parallel_type(从 MySQL 8.0.26)或 slave_parallel_type(在 MySQL 8.0.26 之前)设置为LOGICAL_CLOCK. 从 MySQL 8.0.27(但不适用于早期版本),这是默认设置。

    replica_preserve_commit_order 在某些特定情况下,如and 的描述中列出的 slave_preserve_commit_order,设置 replica_preserve_commit_order=ONslave_preserve_commit_order=ON 无法保留副本上的提交顺序,因此在这些情况下,从副本的中继日志中执行的事务序列中可能仍会出现间隙。

    设置replica_preserve_commit_order=ONslave_preserve_commit_order=ON不防止源二进制日志位置滞后。

  • 源二进制日志位置滞后。即使没有间隙,也有可能 Exec_master_log_pos应用了之后的交易。也就是说,到目前为止所有的交易N 都已被应用,之后没有交易 N被应用,但 Exec_master_log_pos值小于N。在这种情况下, Exec_master_log_pos是一个“低水位线”,落后于最近申请的交易的位置。这只能发生在多线程副本上。启用 replica_preserve_commit_orderslave_preserve_commit_order 不防止源二进制日志位置滞后。

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

  1. 在复制线程运行时,可能存在间隙和半应用事务。
  2. mysqld关闭。clean 和 unclean 关闭都会中止正在进行的事务,并可能留下间隙和半应用事务。
  3. KILL复制线程(使用单线程副本时的 SQL 线程,使用多线程副本时的协调器线程)。这会中止正在进行的事务,并可能留下空白和半应用事务。
  4. 应用程序线程中的错误。这可能会留下空白。如果错误发生在混合事务中,则该事务是半应用的。使用多线程副本时,未收到错误的工作人员会完成其队列,因此可能需要一些时间来停止所有线程。
  5. STOP REPLICA使用多线程副本时。发布后STOP REPLICA,副本等待任何间隙被填补,然后更新 Exec_master_log_pos。这确保了它永远不会留下间隙或源二进制日志位置滞后,除非上述任何情况适用,换句话说,在 STOP REPLICA完成之前,发生错误,或者另一个线程问题KILL,或者服务器重新启动。在这些情况下, STOP REPLICA成功返回。
  6. 如果中继日志中的最后一个事务只收到了一半,并且多线程副本的协调器线程已开始将事务调度给工作人员,则STOP REPLICA最多等待 60 秒以接收事务。在此超时之后,协调器放弃并中止事务。如果交易是混合的,它可能会半途而废。
  7. STOP REPLICA当正在进行的事务仅更新事务表时,在这种情况下它会回滚并STOP REPLICA立即停止。如果正在进行的事务是混合的,则 STOP REPLICA最多等待 60 秒以使事务完成。在此超时之后,它会中止事务,因此它可能会半途而废。

系统变量的全局设置 rpl_stop_replica_timeout(来自 MySQL 8.0.26)或 rpl_stop_slave_timeout(在 MySQL 8.0.26 之前)与停止复制线程的过程无关。它只会使发出问题 STOP REPLICA的客户端返回客户端,但复制线程会继续尝试停止。

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

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

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

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

  4. 如果mysqld以 开头 --relay-log-recovery,则不会对该通道进行恢复,并打印警告。

  5. 如果mysqldump--dump-replicaor 一起使用--dump-slave,则不记录间隙的存在;因此它打印 CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO设置 RELAY_LOG_POS为中的“低水位线”位置 Exec_master_log_pos

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

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

源二进制日志位置信息以二进制格式保存在内部表中 mysql.slave_worker_infoSTART REPLICA [SQL_THREAD\]始终查阅此信息,以便仅应用正确的交易。即使replica_parallel_workersslave_parallel_workers之前已更改为 0 START REPLICA,并且即使 START REPLICAUNTIL子句一起使用,这仍然是正确的。 START REPLICA UNTIL SQL_AFTER_MTS_GAPS仅根据需要应用尽可能多的事务以填补空白。如果 START REPLICAUNTIL告诉它在消耗完所有间隙之前停止的子句一起使用,则它会留下剩余的间隙。

警告

RESET REPLICA删除中继日志并重置复制位置。因此 RESET REPLICA,在具有间隙的多线程副本上发布意味着副本会丢失有关间隙的任何信息,而不会更正间隙。在这种情况下,如果正在使用基于二进制日志位置的复制,则恢复过程将失败。

当使用基于 GTID 的复制 ( GTID_MODE=ON) 并 SOURCE_AUTO_POSITION使用该语句为复制通道设置CHANGE REPLICATION SOURCE TO时,恢复过程不需要旧的中继日志。相反,副本可以使用 GTID 自动定位来计算与源相比它缺少哪些事务。从 MySQL 8.0.26 开始,当使用基于 GTID 的复制时,用于解决多线程副本上的间隙的基于二进制日志位置的复制的过程将被完全跳过。跳过该过程时, START REPLICA UNTIL SQL_AFTER_MTS_GAPS语句的行为会有所不同,并且不会尝试检查事务序列中的间隙。您也可以发出 CHANGE REPLICATION SOURCE TO 语句,在存在间隙的非 GTID 副本上是不允许的。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论