MySQL高可用实践
上QQ阅读APP看书,第一时间看更新

3.4 配置GTID复制

前面解释了许多GTID的原理以及在MySQL复制中所起的作用,并且进行了很多实验加以辅助说明。本节演示如何从头开始一步步配置GTID复制,实验环境同1.2节。这里只讨论在联机情况下进行配置,因为相对于空库或脱机等理想情况,联机配置复制的需求更为典型和常见。

3.4.1 联机配置GTID复制

依照第1章讨论异步复制时得出的结论,本实验使用XtraBackup工具进行联机数据备份。主、从服务器已经进行了以下配置:

  • 在主库上建立复制专属用户。
  • 在主、从库上安装XtraBackup。
  • 配置主库到从库的SSH免密码连接。
  • 停止作为从库的MySQL实例,并清空其数据目录。

这些作为配置MySQL复制的前置步骤,具体操作参考1.3.3小节。下面说明联机配置GTID复制的步骤:

步骤01 检查主库中是否有不支持GTID的操作:

     set global enforce_gtid_consistency=warn;

让服务器在正常工作负载下运行一段时间并监控错误日志,最好包含一天负载最高的时间段,有条件建议观察几天。如果此步骤导致错误日志中出现任何警告,需要调整应用程序,使其仅使用与GTID兼容的功能,并且不能生成与GTID相关的任何警告。这是一个重要步骤,在进行下一步之前,必须确保错误日志中未生成警告。

步骤02 在主库联机设置GTID相关参数:

     set global enforce_gtid_consistency=true;
     set global gtid_mode=off_permissive;
     set global gtid_mode=on_permissive;
     set global gtid_mode=on;

enforce-gtid-consistency启用后,MySQL服务器通过仅允许执行使GTID安全的语句来强制GTID一致性。在启用基于GTID的复制之前,必须将此选项设置为true。enforce_gtid_consistency的可配置值为:

  • false:允许事务违反GTID一致性。
  • true:不允许事务违反GTID一致性。
  • warn:允许事务违反GTID一致性,但在这种情况下会生成警告。

当enforce_gtid_consistency设置为true时,只能使用GTID安全的语句,例如如下操作不能与此选项一起使用:

  • CREATE TABLE ... SELECT语句。
  • 事务内的CREATE TEMPORARY TABLE或DROP TEMPORARY TABLE语句。
  • 更新事务和非事务表的事务或语句。

enforce_gtid_consistency仅在语句进行二进制日志记录时生效。如果在服务器上禁用了二进制日志记录,或者由于过滤器删除了语句而未将语句写入二进制日志,则不会对未记录的语句检查或强制执行GTID一致性。

在包含gtid_mode系统变量的所有MySQL版本中,它都可以设置成on或off。MySQL 5.7.6版本之后,gtid_mode提供了两个新的选项分别为on_permissive和off_permissive。当gtid_mode=on时,无法复制匿名事务,而当gtid_mode=off时,只能复制匿名事务。当gtid_mode=off_permissive时,新事务是匿名的,同时允许复制的事务是GTID或匿名事务。当gtid_mode=on_permissive时,新事务使用GTID,同时允许复制事务为GTID或匿名事务。这意味着可以拥有一个复制拓扑结构,其中包含使用匿名和GTID事务的服务器。例如,具有gtid_mode=on的主库可以有使用gtid_mode=on_permissive从库。gtid_mode在主、从库上的兼容性以及能否使用自动定位如表3-1所示,每个条目的含义如下:

  • Y:主库和从库的gtid_mode兼容。
  • N:主库和从库的gtid_mode不兼容。
  • *:自动定位可与此组合一起使用。

表3-1 gtid_mode兼容性

联机设置gtid_mode时,只能基于OFF、OFF_PERMISSIVE、ON_PERMISSIVE、ON的顺序一次改变一步。例如,如果gtid_mode当前设置为OFF_PERMISSIVE,则可以更改为OFF或ON_PERMISSIVE,但不能直接更改为ON,否则会报以下错误:

这样实现是为了确保服务器能够正确处理从匿名事务更改为GTID事务的过程,此过程中可能同时包含这两种模式的事务。在gtid_mode=on和gtid_mode=off之间切换时,GTID状态(也就是gtid_executed的值)是持久化的,因此不管gtid_mode的类型如何更改,都可确保始终保留服务器应用的GTID集。无论当前选择的gtid_mode如何,与GTID相关的字段都会显示正确的信息。显示GTID集的字段,例如performance_schema.replication_connection_status表中的gtid_executed、gtid_purged、received_transaction_set以及show slave status的GTID相关结果,在没有GTID时返回空字符串。显示单个GTID的字段,如performance_schema.replication_applier_status_by_worker表中的current_transaction,在未使用GTID时显示ANONYMOUS。从库使用gtid_mode=on复制提供了自动定位的功能。

当前选择的gtid_mode也会影响gtid_next变量。表3-2显示了服务器对gtid_mode和gtid_next不同值的行为。每个条目的含义如下:

  • ANONYMOUS:生成匿名事务。
  • Error:生成错误并且无法执行SET GTID_NEXT。
  • UUID:NUMBER:使用指定的UUID:NUMBER生成GTID。
  • New GTID:使用自动生成的数字生成GTID。

表3-2 gtid_mode和gtid_next不同值的行为

当二进制日志关闭且gtid_next设置为AUTOMATIC时,不会生成GTID,这与先前版本的行为一致。注意,为了保证主从数据一致性和实例恢复的性能,在MySQL 8中作为一项基本原则,除非有特殊需求,与复制相关的其他系统变量最好保持默认值,包括但不限于下面所列出的系统变量:

  • autocommit=ON
  • log_bin=ON
  • log_slave_updates=ON
  • innodb_flush_log_at_trx_commit=1
  • sync_binlog=1
  • master_info_repository=TABLE
  • relay_log_info_repository=TABLE
  • relay_log_recovery=OFF
  • binlog_gtid_simple_recovery=ON
  • innodb_replication_delay=0

(1)使用xtrabackup备份并传输:

使用xtrabackup的一个好处是,不必考虑从gtid_mode=off到gtid_mode=on的过程中是否存在正在进行的匿名事务。xtrabackup执行的是物理备份,主库上无论是匿名事务还是GTID事务,最终数据文件和二进制日志文件都会被复制到从库,并且在恢复备份、启动实例和复制后,可以使用GTID的自动定位功能找到初始复制点。

(2)在从库中恢复备份:

     xtrabackup --prepare --target-dir=/usr/local/mysql/data/

(3)在从库的配置文件中添加以下选项:

(4)启动从库:

     mysqld_safe --defaults-file=/etc/my.cnf &

(5)在从库启动复制:

可以在slave status中看到复制正在进行,Retrieved_Gtid_Set和Executed_Gtid_Set不断增加,Seconds_Behind_Master逐渐缩小至0。

(6)将GTID参数添加到主库的配置文件中:

     gtid_mode=on
     enforce-gtid-consistency=true

至此完成联机配置GTID复制。

3.4.2 联机更改复制模式

如果已经在未启用GITD的情况下配置了主从复制,可以联机将复制模式修改为GTID以及自动定位。由于整个过程不需要停止MySQL实例,因此这种方式适合在生产环境中使用。开始前确保MySQL服务器满足以下前提条件:

  • 复制拓扑结构中的所有服务器都必须使用MySQL 5.7.6或更高版本。除非拓扑结构中的所有服务器都使用此版本,否则无法在任何单个服务器上联机启用GTID事务。
  • 所有服务器的gtid_mode默认设置为OFF。

以下过程可以随时暂停,之后再恢复,这使得该过程具有容错能力。如果过程中出现任何不相关的错误,可以先暂停过程解决问题,然后再从停止的地方继续。但至关重要的一点是,在继续下一步之前必须完成之前的步骤。联机改为GTID复制的步骤如下:

步骤01 在每台服务器上执行:set global enforce_gtid_consistency=warn;保证所有操作都与GTID兼容,并且确保错误日志中没有GTID的相关警告。

步骤02 在每台服务器上执行:set global enforce_gtid_consistency=true;。

步骤03 在每台服务器上执行:set global gtid_mode=off_permissive;哪台服务器首先执行此语句无关紧要,重要的是在开始下一步之前,在所有服务器完成此步骤。

步骤04 在每台服务器上执行:set global gtid_mode=on_permissive;。

步骤05 在每台服务器上,等待状态变量ongoing_anonymous_transaction_count为0。检查方法:show status like 'ongoing_anonymous_transaction_count';。

步骤06 如果二进制日志还用于复制以外的其他目的,如基于时间点的恢复等,需要在执行flush logs后备份二进制日志文件。包含匿名事务的二进制日志在下一步执行之后无法使用。完成此步后,确保拓扑中的任何位置都不存在匿名事务。

步骤07 在每台服务器上执行:set global gtid_mode=on;。

步骤08 在每个从库上执行以下操作:

     stop slave;
     change master to master_auto_position = 1;
     start slave;

步骤09 在每台服务器上,将gtid-mode=on和enforce_gtid_consistency=true添加到my.cnf配置文件。

现在可以保证所有事务都具有GTID(步骤5或更早生成的事务已经过处理),已经改为GTID复制模式。

联机将GTID事务复制改为匿名事务复制模式的过程基本是上述步骤的逆过程,唯一不同的是等待记录事务复制的方式。

步骤01 在每个从库上执行以下操作,xxx可以从show slave status输出的Master_Log_File和Read_Master_Log_Pos获得:

步骤02 在每台服务器上执行:set global gtid_mode=on_permissive;。

步骤03 在每台服务器上执行:set global gtid_mode=off_permissive;。

步骤04 在每台服务器上,等待变量@@GLOBAL.GTID_OWNED等于空字符串。检查方法:select @@global.gtid_owned;此时复制正常进行,但slave status中的Retrieved_Gtid_Set和Executed_Gtid_Set值不再变化。

步骤05 如果二进制日志还用于复制以外的其他目的(如基于时间点的恢复等),执行FLUSH LOGS后再备份二进制日志文件。包含GTID事务的二进制日志在下一步执行之后无法使用。完成此步骤后,确保拓扑结构中的任何位置都不存在GTID事务。

步骤06 在每台服务器上执行:set global gtid_mode=off;。

步骤07 在每台服务器上执行:set global enforce_gtid_consistency=false;。

步骤08 在每台服务器上,在my.cnf配置文件中设置gtid-mode=off和enforce_gtid_consistency=false。

3.4.3 GTID相关系统变量

前面已经在各个地方分散介绍过很多GTID相关的系统变量,如gtid_executed、gtid_next、gtid_purged、gtid_mode等,下面对MySQL 8中的重要GTID系统变量加以简单整理。

  • binlog_gtid_simple_recovery:布尔类型全局变量,控制MySQL启动时从哪些binlog文件中寻找GTID,默认值为true。当binlog_gtid_simple_recovery=true时,初始化gtid_executed和gtid_purged值时只读取最旧和最新的binlog文件,否则需要遍历所有binlog文件。
  • enforce_gtid_consistency:枚举类型全局变量,指示是否强制GTID数据一致性,有效值为OFF、ON和WARN,默认值为OFF。
  • gtid_executed:全局和会话级别都可以用,用来保存已经执行过的GTID集合。
  • gtid_executed_compression_period:整型全局变量,指示压缩mysql.gtid_executed表之前允许的事务数,默认值为1000。使用二进制日志时该值不起作用,而是在每个二进制日志轮转时压缩mysql.gtid_executed表。
  • gtid_mode:枚举类型全局变量,控制是否启用GTID功能,有效值为OFF、OFF_PERMISSIVE、ON_PERMISSIVE和ON,默认值为OFF。联机设置时,只能按顺序一步步修改。
  • gtid_next:会话级枚举变量,用于指定如何获取下一个GTID。有效值为AUTOMATIC、ANONYMOUS和UUID:NUMBER,默认值为AUTOMATIC。
  • gtid_owned:内部使用的只读变量,指示当前正在使用的GTID以及拥有它的线程ID。
  • gtid_purged:全局变量,设置已经执行但在binlog中被清除的GTID集合,是gtid_executed的子集。