本节介绍如何在已经在线并使用匿名事务的服务器上启用 GTID 事务,以及可选的自动定位。此过程不需要将服务器离线,适合在生产环境中使用。但是,如果您有将服务器离线以启用 GTID 事务的可能性,该过程将更加容易。
您可以设置复制通道,将 GTID 分配给尚未分配 GTID 的复制事务。此功能允许从不使用基于 GTID 的复制的源服务器复制到使用基于 GTID 的复制的副本。如果可能,如本过程所述,在复制源服务器上启用 GTID,请使用这种方法。分配 GTID 是为无法启用 GTID 的复制源服务器设计的。有关此选项的更多信息,请参阅第 19.1.3.6 节,“从没有 GTID 的源到有 GTID 的副本进行复制”。
在开始之前,请确保所有服务器上的gtid_mode
都是 OFF
。
以下过程可以在任何时候暂停,并在以后从暂停的地方恢复,或者通过跳转到第 19.1.4.3 节,“在线禁用 GTID 事务” 中禁用 GTID 的在线过程的相应步骤来反转。这使得过程具有容错性,因为在过程执行过程中出现的任何无关问题都可以像往常一样处理,然后在停止的地方继续执行过程。
要启用 GTID 事务,您必须在继续执行下一步之前完成以下每个步骤。
在每台服务器上,执行以下语句
SET @@GLOBAL.enforce_gtid_consistency = WARN;
让服务器使用您的正常工作负载运行一段时间,并监控日志。如果此步骤导致日志中出现任何警告,请调整您的应用程序,使其仅使用兼容 GTID 的功能,并且不会生成任何警告。
在每台服务器上,执行以下语句
SET @@GLOBAL.enforce_gtid_consistency = ON;
在每台服务器上,执行以下语句
SET @@GLOBAL.gtid_mode = OFF_PERMISSIVE;
服务器执行此语句的顺序无关紧要,但所有服务器必须在开始下一步之前执行此语句。
在每台服务器上,执行以下语句
SET @@GLOBAL.gtid_mode = ON_PERMISSIVE;
与上一步一样,哪个服务器先执行语句无关紧要,只要每个服务器在继续执行之前执行此语句即可。
在每台服务器上,等待
Ongoing_anonymous_transaction_count
等于0
。您可以使用SHOW STATUS
语句检查其值,例如mysql> SHOW STATUS LIKE 'Ongoing%'; +-------------------------------------+-------+ | Variable_name | Value | +-------------------------------------+-------+ | Ongoing_anonymous_transaction_count | 0 | +-------------------------------------+-------+ 1 row in set (0.00 sec)
在副本上,理论上可能出现
0
然后再次出现非零值。这不是问题,只要它至少有一次是0
即可。等待所有在之前步骤中生成的事务复制到所有服务器。您可以在不停止更新的情况下执行此操作;重要的是,所有匿名事务在继续执行之前都已复制。
请参阅第 19.1.4.4 节,“验证匿名事务的复制”,了解一种检查所有匿名事务是否已复制到所有服务器的方法。
如果您将二进制日志用于复制以外的任何用途(例如,时间点备份和恢复),请等到不再需要包含没有 GTID 的事务的旧二进制日志时。
例如,在所有事务都已复制后,您可以在进行备份的服务器上执行
FLUSH LOGS
。然后,您可以显式地进行备份,或者等待您可能设置的任何定期备份例程的下次迭代。理想情况下,您应该等待服务器清除上一步完成后存在的全部二进制日志,以及之前进行的任何备份到期。
请记住,包含匿名事务(即,没有 GTID 的事务)的二进制日志不能在下一步之后使用,之后您必须确保没有任何没有 GTID 的事务在任何服务器上处于未提交状态。
在每台服务器上,执行以下语句
SET @@GLOBAL.GTID_MODE = ON;
在每个服务器上,将
gtid-mode=ON
和enforce-gtid-consistency=ON
添加到my.cnf
中。这保证了 GTID 将用于所有尚未处理的事务。要开始使用 GTID 协议以便以后执行自动故障转移,请在每个副本上执行下一组语句。如果您使用多源复制,请对每个通道(包括FOR CHANNEL
子句)执行此操作。channel
STOP REPLICA [FOR CHANNEL 'channel']; CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 1 [FOR CHANNEL 'channel']; START REPLICA [FOR CHANNEL 'channel'];