16.1.3.3 GTID 自动定位

GTID 替换了先前为确定开始,停止或恢复源和副本之间的数据流所需的点而需要的文件偏移对。使用 GTID 时,直接从复制数据流中获取副本与源同步所需的所有信息。

要使用基于 GTID 的复制来启动副本,请不要在用于指示副本从给定源复制的更改为主语句中包含MASTER_LOG_FILEMASTER_LOG_POS选项。这些选项指定日志文件的名称和文件中的起始位置,但是使用 GTID 时,副本不需要此 nonlocal 数据。相反,您需要启用MASTER_AUTO_POSITION选项。有关使用基于 GTID 的复制配置和启动源和副本的完整说明,请参见第 16.1.3.4 节,“使用 GTID 设置复制”

默认情况下,禁用MASTER_AUTO_POSITION选项。如果副本上启用了多源复制,则需要为每个适用的复制通道设置选项。再次禁用MASTER_AUTO_POSITION选项会使副本恢复为基于文件的复制,在这种情况下,您还必须指定MASTER_LOG_FILEMASTER_LOG_POS选项之一或全部。

当副本启用了 GTID(GTID_MODE=ONON_PERMISSIVE,OFF_PERMISSIVE)并且启用了MASTER_AUTO_POSITION选项时,将激活自动定位以连接到源。源必须设置GTID_MODE=ON才能成功连接。在最初的握手中,副本发送一个 GTID 集,其中包含它已接收,已提交或同时发生的事务。此 GTID 集等于gtid_executed系统变量(@@GLOBAL.gtid_executed)中的 GTID 集和在 Performance Schema replication_connection_statustable 中记录为已接收事务的 GTID 集(语句SELECT RECEIVED_TRANSACTION_SET FROM PERFORMANCE_SCHEMA.replication_connection_status的结果)的并集。

源通过发送记录在其二进制日志中的所有事务进行响应,这些事务的 GTID 未包含在副本发送的 GTID 集中。为此,源首先通过检查其每个二进制日志文件的 Headers 中的Previous_gtids_log_event(从最新的开始)来标识要开始使用的适当二进制日志文件。当源找到第一个Previous_gtids_log_event时,其中不包含缺少副本的事务,它将以该二进制日志文件开头。此方法非常有效,并且如果副本位于大量二进制日志文件之后,则仅花费大量时间。然后,源读取该二进制日志文件中的事务,以及直到当前文件为止的后续文件,发送带有副本丢失的 GTID 的事务,并跳过副本发送的 GTID 集中的事务。副本接收到第一个丢失的事务之前所经过的时间取决于其在二进制日志文件中的偏移量。此交换可确保源仅发送具有尚未接收或提交副本的 GTID 的事务。如果副本从多个来源接收事务,例如菱形拓扑,则自动跳过功能可确保不会两次应用事务。

如果已从源发送的任何事务已从源的二进制日志中清除,或已通过另一种方法添加到gtid_purged系统变量中的 GTID 集中,则源将错误 ER_MASTER_HAS_PURGED_REQUIRED_GTIDS 发送到副本,复制将执行无法启动。标识丢失的清除事务的 GTID,并在警告消息 ER_FOUND_MISSING_GTIDS 中的源错误日志中列出。副本无法自动从此错误中恢复,因为已清除了追赶源所需的部分事务历史记录。在未启用MASTER_AUTO_POSITION选项的情况下尝试重新连接只会导致副本上已清除的事务丢失。从这种情况中恢复的正确方法是,副本从另一个源复制 ER_FOUND_MISSING_GTIDS 消息中列出的丢失的事务,或者将副本替换为从较新的备份创建的新副本。考虑修改源上的二进制日志有效期限,以确保不会再次发生这种情况。

如果在事务交换期间发现副本已接收或已提交 Transaction,且 Transaction 源具有 GTID 中的 UUID,但源本身没有记录,则源将错误 ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER 发送给副本,而复制不会开始。如果未设置sync_binlog=1的源遇到电源故障或 os 崩溃,并且丢失了尚未同步到二进制日志文件但已被副本接收的已提交事务,则可能发生这种情况。重新启动后,如果有任何 Client 端在源上提交事务,则源和副本可能会分开,这可能导致源和副本对不同事务使用相同 GTID 的情况。从这种情况中恢复的正确方法是手动检查源和副本是否分开。如果相同的 GTID 现在用于不同的事务,则您需要根据需要对单个事务执行手动冲突解决,或者从复制拓扑中删除源或副本。如果问题仅在于源上缺少事务,则可以将源改为副本,允许它赶上复制拓扑中的其他服务器,然后在需要时再次使其成为源。