基于已有的位置点主从复制架构在线开启/关闭 GTID 复制主库192.168.195.141从库192.168.195.1421. 什么是 GTIDGTIDGlobal Transaction Identifier全局事务ID会为每个事务分配一个唯一的事务ID格式如下source_id:transaction_idsource_id事务是在哪个实例上产生的通常用实例的 server_uuid 来表示。transaction_id事务的序列号按照事务提交的顺序从1开始分配。这样可保证 GTID 在整个复制拓扑中都是全局唯一的。2. GTID 的优点全局唯一标识符GTID 为每个事务提供一个全局唯一的标识符避免了在复制拓扑中使用二进制日志文件和位置的复杂性。简化配置使用 GTID 可以更轻松地配置主从复制无需手动跟踪二进制日志文件和位置。故障恢复GTID 简化了故障恢复过程使得在主从之间重新建立复制关系更为容易。避免重复应用GTID 可以帮助防止在主从之间重复应用相同的事务提高数据一致性。3. 当前环境确认3.1 主库配置文件 /etc/my.cnf141[client] socket /data/mysql/3306/data/mysql.sock [mysqld] basedir /usr/local/mysql datadir /data/mysql/3306/data user mysql port 3306 socket /data/mysql/3306/data/mysql.sock log_error /data/mysql/3306/data/mysqld.err log_timestamps system log-bin mysql-bin server-id 13.2 从库配置文件 /etc/my.cnf142[client] socket /data/mysql/3306/data/mysql.sock [mysqld] basedir /usr/local/mysql datadir /data/mysql/3306/data user mysql port 3306 socket /data/mysql/3306/data/mysql.sock log_error /data/mysql/3306/data/mysqld.err log_timestamps system server-id 23.3 当前 GTID 状态主库141 gtid_mode OFF enforce_gtid_consistency OFF 从库142 gtid_mode OFF enforce_gtid_consistency OFF Auto_Position 0基于位置点复制4. GTID 相关参数mysqlshowvariableslike%gtid%;--------------------------------------------------------------------------------|Variable_name|Value|--------------------------------------------------------------------------------|binlog_gtid_simple_recovery|ON||enforce_gtid_consistency|OFF||gtid_executed|||gtid_executed_compression_period|0||gtid_mode|OFF||gtid_next|AUTOMATIC||gtid_owned|||gtid_purged|||session_track_gtids|OFF|--------------------------------------------------------------------------------参数解释gtid_mode是否开启 GTID 复制。在 MySQL 5.7.6 之前如果要开启或关闭 GTID 复制必须重启实例。从 MySQL 5.7.6 开始可在线开启 GTID 复制。gtid_mode 可设置以下选项OFF所有新的事务和复制中的事务都必须是匿名事务非 GTID 事务。OFF_PERMISSIVE新的事务是匿名事务复制中的事务既可以是匿名事务也可以是 GTID 事务。ON_PERMISSIVE新的事务是 GTID 事务复制中的事务既可以是匿名事务也可以是 GTID 事务。ON所有新的事务和复制中的事务都必须是 GTID 事务。注意对于该参数的修改只能逐步修改不能直接修改。如将 OFF 调整为 ON只能按照OFF - OFF_PERMISSIVE - ON_PERMISSIVE - ON的顺序进行修改。enforce_gtid_consistency用来检测是否有违反 GTID 限制的 SQL。OFF关闭检测。ON开启检测。如果操作违反了限制会直接报错。WARN开启检测。如果操作违反了限制不会报错只是会在错误日志中打印 Warning。注意如果要将 gtid_mode 设置为 ON则 enforce_gtid_consistency 必须为 ON。gtid_executedMySQL 已经执行过的 GTID 集。gtid_purgedMySQL 已经清除的 GTID 集通常是被删除的 binlog 中的 GTID 集。gtid_next用来设置下一个 GTID 值只能在会话级别设置。AUTOMATIC自动获取下一个 GTID 值默认值。ANONYMOUS匿名事务。UUID:NUMBER显式设置 GTID 值。常用于主从复制环境从库跳过指定事务。gtid_executed_compression_periodMySQL 会定期对 mysql.gtid_executed 表进行压缩。MySQL 8.0.23 开始默认值为 0会根据需要进行压缩。5. GTID 复制的限制不支持CREATE TABLE ... SELECT ...语句。从 MySQL 8.0.21 开始该限制被取消。不允许在事务、存储过程、函数、触发器中执行CREATE TEMPORARY TABLE或DROP TEMPORARY TABLE操作。从 MySQL 8.0.13 开始如果 binlog 格式为 ROW 或 MIXED该限制被取消。不能将 InnoDB 表和非 InnoDB 表放到一个事务内操作。6. 在线开启 GTID 复制步骤1分别在主从上设置 ENFORCE_GTID_CONSISTENCY WARN观察一段时间确保错误日志中没有生成警告。-- 主库141执行SETGLOBAL.ENFORCE_GTID_CONSISTENCYWARN;-- 从库142执行SETGLOBAL.ENFORCE_GTID_CONSISTENCYWARN;步骤2分别在主从上设置 ENFORCE_GTID_CONSISTENCY ON-- 主库141执行SETGLOBAL.ENFORCE_GTID_CONSISTENCYON;-- 从库142执行SETGLOBAL.ENFORCE_GTID_CONSISTENCYON;步骤3分别在主从上设置 GTID_MODE OFF_PERMISSIVE次序任意。-- 主库141执行SETGLOBAL.GTID_MODEOFF_PERMISSIVE;-- 从库142执行SETGLOBAL.GTID_MODEOFF_PERMISSIVE;步骤4分别在主从上设置 GTID_MODE ON_PERMISSIVE-- 主库141执行SETGLOBAL.GTID_MODEON_PERMISSIVE;-- 从库142执行SETGLOBAL.GTID_MODEON_PERMISSIVE;步骤5分别在主从上检查 ONGOING_ANONYMOUS_TRANSACTION_COUNT 的值为零-- 主库141执行SHOWSTATUSLIKEONGOING_ANONYMOUS_TRANSACTION_COUNT;-- ---------------------------------------------- | Variable_name | Value |-- ---------------------------------------------- | Ongoing_anonymous_transaction_count | 0 |-- ---------------------------------------------- 从库142执行SHOWSTATUSLIKEONGOING_ANONYMOUS_TRANSACTION_COUNT;-- ---------------------------------------------- | Variable_name | Value |-- ---------------------------------------------- | Ongoing_anonymous_transaction_count | 0 |-- --------------------------------------------说明该参数用来统计正在进行的匿名事务的数量若为 0则继续进行下一步。步骤6等待从库匿名事务应用完毕首先通过 show master status 获取主库当前二进制日志的位置点-- 主库141执行mysqlshowmasterstatus;-- --------------------------------------------------------------------------------- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |-- --------------------------------------------------------------------------------- | mysql-bin.000004 | 157 | | | |-- -------------------------------------------------------------------------------其次在从库上执行 MASTER_POS_WAIT 函数-- 从库142执行mysqlselectMASTER_POS_WAIT(mysql-bin.000004,157);-- --------------------------------------------- | MASTER_POS_WAIT(mysql-bin.000004,157) |-- --------------------------------------------- | 0 |-- -------------------------------------------说明该命令会一直阻塞直到指定位置点的事务在从库上应用。返回 0 表示已应用完毕。步骤7分别在主从上设置 GTID_MODE ON-- 主库141执行setglobalgtid_modeON;-- 从库142执行setglobalgtid_modeON;步骤8修改主从的配置文件将 GTID 相关参数加上主库 /etc/my.cnf141增加gtid_mode ON enforce_gtid_consistency ON完整配置文件[client] socket /data/mysql/3306/data/mysql.sock [mysqld] basedir /usr/local/mysql datadir /data/mysql/3306/data user mysql port 3306 socket /data/mysql/3306/data/mysql.sock log_error /data/mysql/3306/data/mysqld.err log_timestamps system log-bin mysql-bin server-id 1 gtid_mode ON enforce_gtid_consistency ON从库 /etc/my.cnf142增加gtid_mode ON enforce_gtid_consistency ON完整配置文件[client] socket /data/mysql/3306/data/mysql.sock [mysqld] basedir /usr/local/mysql datadir /data/mysql/3306/data user mysql port 3306 socket /data/mysql/3306/data/mysql.sock log_error /data/mysql/3306/data/mysqld.err log_timestamps system server-id 2 gtid_mode ON enforce_gtid_consistency ON步骤9将基于 binlog 位置点的复制修改为 GTID 复制-- 从库142执行stop slave;change mastertomaster_auto_position1;startslave;说明使用 GTID 复制后只需设置MASTER_AUTO_POSITION 1无需指定MASTER_LOG_FILE和MASTER_LOG_POS。验证 GTID 复制状态-- 从库142执行showslavestatus\GSlave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 Retrieved_Gtid_Set: Executed_Gtid_Set: d5728692-8354-11f1-8acf-000c29048d1f:1 Auto_Position: 1-- 主库141执行showvariableslike%gtid%;gtid_mode ON enforce_gtid_consistency ON gtid_executed d5728692-8354-11f1-8acf-000c29048d1f:1数据同步测试-- 主库141执行INSERTINTOtest_rep.t1VALUES(2,gtid_test);SELECT*FROMtest_rep.t1;-- ------------------- | id | name |-- ------------------- | 1 | master_data |-- | 2 | gtid_test |-- ------------------- 从库142执行SELECT*FROMtest_rep.t1;-- ------------------- | id | name |-- ------------------- | 1 | master_data |-- | 2 | gtid_test |-- -----------------✅ GTID 复制开启后数据同步正常。7. 在线关闭 GTID 复制步骤1将从库上基于 GTID 的复制修改为基于 binlog 位置点的复制1关闭 slave-- 从库142执行stop slave;2查看 show slave status 的值-- 从库142执行showslavestatus\G获取Relay_Master_Log_File和Exec_Master_Log_Pos的值Relay_Master_Log_File: mysql-bin.000005 Exec_Master_Log_Pos: 4483执行 change master to 语句-- 从库142执行change mastertomaster_auto_position0,master_log_filemysql-bin.000005,master_log_pos448;4开启复制-- 从库142执行startslave;验证Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 Auto_Position: 0步骤2分别在主从上设置 GTID_MODE ON_PERMISSIVE-- 主库141执行setglobalgtid_modeON_PERMISSIVE;-- 从库142执行setglobalgtid_modeON_PERMISSIVE;步骤3分别在主从上设置 GTID_MODE OFF_PERMISSIVE-- 主库141执行setglobalgtid_modeOFF_PERMISSIVE;-- 从库142执行setglobalgtid_modeOFF_PERMISSIVE;步骤4分别在主从上检查 gtid_owned 变量的值-- 主库141执行selectglobal.gtid_owned;-- ---------------------- | global.gtid_owned |-- ---------------------- | |-- ---------------------- 从库142执行selectglobal.gtid_owned;-- ---------------------- | global.gtid_owned |-- ---------------------- | |-- --------------------如果为空则继续进行下一步。步骤5等待所有的 GTID 事务应用完基于 MASTER_POS_WAIT 函数-- 主库141执行showmasterstatus;-- ------------------------------------------------------------------------------------------------------ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |-- ------------------------------------------------------------------------------------------------------ | mysql-bin.000007 | 197 | | | d5728692-8354-11f1-8acf-000c29048d1f:1 |-- ------------------------------------------------------------------------------------------------------ 从库142执行selectMASTER_POS_WAIT(mysql-bin.000007,197);-- --------------------------------------------- | MASTER_POS_WAIT(mysql-bin.000007,197) |-- --------------------------------------------- | 0 |-- -------------------------------------------步骤6分别在主从上设置 GTID_MODE OFF-- 主库141执行setglobalgtid_modeOFF;-- 从库142执行setglobalgtid_modeOFF;步骤7修改主从的配置文件将 GTID 相关参数显式设置为 OFF主库 /etc/my.cnf141[client] socket /data/mysql/3306/data/mysql.sock [mysqld] basedir /usr/local/mysql datadir /data/mysql/3306/data user mysql port 3306 socket /data/mysql/3306/data/mysql.sock log_error /data/mysql/3306/data/mysqld.err log_timestamps system log-bin mysql-bin server-id 1 gtid_mode OFF enforce_gtid_consistency OFF从库 /etc/my.cnf142[client] socket /data/mysql/3306/data/mysql.sock [mysqld] basedir /usr/local/mysql datadir /data/mysql/3306/data user mysql port 3306 socket /data/mysql/3306/data/mysql.sock log_error /data/mysql/3306/data/mysqld.err log_timestamps system server-id 2 gtid_mode OFF enforce_gtid_consistency OFF验证关闭 GTID 后的状态-- 主库141执行showvariableslike%gtid%;-- gtid_mode OFF-- enforce_gtid_consistency OFF-- 从库142执行showslavestatus\G-- Slave_IO_Running: Yes-- Slave_SQL_Running: Yes-- Seconds_Behind_Master: 0-- Auto_Position: 0数据同步测试-- 主库141执行INSERTINTOtest_rep.t1VALUES(3,after_gtid_off);SELECT*FROMtest_rep.t1;-- ----------------------- | id | name |-- ----------------------- | 1 | master_data |-- | 2 | gtid_test |-- | 3 | after_gtid_off |-- ----------------------- 从库142执行SELECT*FROMtest_rep.t1;-- ----------------------- | id | name |-- ----------------------- | 1 | master_data |-- | 2 | gtid_test |-- | 3 | after_gtid_off |-- ---------------------✅ 关闭 GTID 后主从复制仍然正常数据同步 OK。8. 当前最终状态GTID 已重新在线开启当前环境为 GTID 复制模式主库141 gtid_mode ON enforce_gtid_consistency ON gtid_executed d5728692-8354-11f1-8acf-000c29048d1f:1 从库142 gtid_mode ON enforce_gtid_consistency ON Auto_Position 1 Slave_IO_Running Yes Slave_SQL_Running Yes9. gtid_mode 修改顺序总结操作修改顺序在线开启 GTIDOFF → OFF_PERMISSIVE → ON_PERMISSIVE → ON在线关闭 GTIDON → ON_PERMISSIVE → OFF_PERMISSIVE → OFF注意不能跳步修改必须逐步进行。开启时 enforce_gtid_consistency 需先设为 WARN 观察再设为 ON最后再逐步修改 gtid_mode。