根据您的复制配置,从中继日志执行的事务序列可能出现不一致的情况。本节解释如何避免不一致并解决它们引起的任何问题。
可能存在以下类型的不一致:
Half-applied事务.更新非事务性表的事务应用了它的部分更改,但不是全部更改。
差距.当给定一个有序的事务序列,在该序列中较后的事务在该序列中较前的其他事务之前应用时,就会出现外部化事务集中的间隙。只有在使用多线程副本时才会出现间隙。为避免间隙发生,设置
replica_preserve_commit_order = 1
(从MySQL 8.0.26)slave_preserve_commit_order = 1
(在MySQL 8.0.26之前)。在MySQL 8.0.18之前,此设置要求二进制日志记录(log_bin
)和副本更新日志记录(log_replica_updates
或log_slave_updates
)也是启用的,这是MySQL 8.0的默认设置。从MySQL 8.0.19开始,二进制日志记录和副本更新日志记录在副本上不需要设置replica_preserve_commit_order = 1
或slave_preserve_commit_order = 1
,如果需要,可以禁用。在所有版本中,设置replica_preserve_commit_order = 1
或slave_preserve_commit_order = 1
要求replica_parallel_type
(从MySQL 8.0.26)slave_parallel_type
被设置为LOGICAL_CLOCK
,这是不默认设置。注意,在某些特定情况下,如描述中列出的replica_preserve_commit_order
而且slave_preserve_commit_order
,设置replica_preserve_commit_order = 1
或slave_preserve_commit_order = 1
不能保留副本上的提交顺序,因此在这些情况下,从副本的中继日志执行的事务序列中仍可能出现空白。源二进制日志位置滞后.即使在没有缺口的情况下,也有可能交易之后
Exec_master_log_pos
已经被应用。也就是说,所有的交易都要按时完成N
已经申请,之后没有事务N
已经申请了,但是Exec_master_log_pos
值小于N
.在这种情况下,Exec_master_log_pos
是一个”最低点”,并落后于最近应用的事务的位置。这只能发生在多线程副本上。启用replica_preserve_commit_order
或slave_preserve_commit_order
不能防止源二进制日志位置滞后。
以下场景与半应用事务、间隙和源二进制日志位置滞后的存在有关:
在运行复制线程时,可能会出现间隙和应用了一半的事务。
mysqld关闭。干净的和不干净的关闭都会中止正在进行的事务,并可能留下间隙和应用了一半的事务。
杀了
复制线程(使用单线程副本时为SQL线程,使用多线程副本时为协调线程)。这会中止正在进行的事务,并可能留下间隙和未应用的事务。应用程序线程错误。这可能会留下空白。如果错误是在混合事务中,则该事务只应用了一半。当使用多线程副本时,没有收到错误的worker会完成他们的队列,因此可能需要时间来停止所有线程。
停止|副本slave
当使用多线程副本时。发行后停止|副本slave
,副本等待任何空白被填补,然后更新Exec_master_log_pos
.这确保它不会留下空白或源二进制日志位置滞后,除非上面的任何情况都适用,换句话说,以前停止|副本slave
完成时,要么发生错误,要么出现另一个线程问题杀了
,否则服务器将重启。在这些情况下,停止|副本slave
成功返回。如果中继日志中的最后一个事务只接收到一半,而多线程副本的协调线程已经开始将事务调度到工作线程,那么
停止|副本slave
等待最多60秒以接收事务。在此超时之后,协调器将放弃并中止事务。如果事务是混合的,它可能只完成了一半。停止|副本slave
当使用单线程副本时。如果正在进行的事务只更新事务表,则它将被回滚和停止|副本slave
立即停止。如果正在进行的事务是混合的,停止|副本slave
等待事务完成的时间最长为60秒。在此超时之后,它将中止事务,因此事务可能只完成了一半。
系统变量的全局设置rpl_stop_replica_timeout
(从MySQL 8.0.26)rpl_stop_slave_timeout
(在MySQL 8.0.26之前)与停止复制线程的过程无关。这只会让客户产生问题停止|副本slave
返回到客户机,但是复制线程继续试图停止。
如果复制区域通道存在间隙,会导致以下后果:
复制数据库可能处于源上从未存在过的状态。
这个领域
Exec_master_log_pos
在显示副本|的slave状态
仅仅是一个”最低点”.换句话说,出现在该位置之前的事务保证已提交,而出现在该位置之后的事务可能已提交或未提交。如果mysqld是开始
——relay-log-recovery
时,不会对该通道进行恢复,并打印警告。如果, mysqldump是使用
——dump-replica
或——dump-slave
,它没有记录间隙的存在;因此它打印将复制源更改为
|改变主
与RELAY_LOG_POS
设置为”最低点”位置Exec_master_log_pos
.在另一个服务器上应用转储并启动复制线程后,再次复制位置之后出现的事务。注意,如果启用了gtid,这是无害的(但是,在这种情况下,不建议使用它
——dump-replica
或——dump-slave
).
如果复制区域通道有源二进制日志位置滞后但没有间隙,则适用上述情况2至5,但不适用情况1。
源二进制日志位置信息以二进制格式保存在内部表中mysql.slave_worker_info
.启动复制| slave [sql_thread]
总是查询此信息,以便它只应用正确的事务。这仍然是正确的replica_parallel_workers
或slave_parallel_workers
是否已更改为0启动|副本slave
,即使启动|副本slave
是使用直到
条款。启动副本| slave直到sql_after_mts_spaces
只应用所需的事务数量,以填补空白。如果启动|副本slave
是使用直到
子句告诉它在耗尽所有间隙之前停止,然后它留下剩余的间隙。
重置副本| slave
删除中继日志并重置复制位置。因此发行重置副本| slave
在有间隙的多线程副本上,意味着副本会丢失关于间隙的任何信息,而不会纠正间隙。在这种情况下,如果使用了基于二进制日志位置的复制,恢复过程将失败。
当使用基于gtid的复制时(GTID_MODE =对
),SOURCE_AUTO_POSITION
复制区域通道使用将复制源更改为
语句,则恢复过程不需要旧的中继日志。相反,副本可以使用GTID自动定位来计算与源相比它丢失了哪些事务。从MySQL 8.0.26开始,当使用基于gtid的复制时,基于二进制日志位置的复制来解决多线程副本上的空白的过程被完全跳过。当跳过该过程时,a启动副本直到sql_after_mts_spaces
语句的行为不同,并且不尝试检查事务序列中的间隙。你也可以发出将复制源更改为
语句,这些语句在有间隙的非gtid副本上是不允许的。