MySQL 5.7 禁用GTID联机事务

在线禁用GTID事务
如何在已经在线的服务器上禁用GTID事务。此过程不需要使服务器离线,适合在生产环境中使用。但是,如果您有可能在禁用GTIDs模式时 使服务器离线,那么这个过程会更容易。

该过程类似于在服务器在线时启用GTID事务,但步骤相反。唯一不同的是等待已记录事务复制的时间点。

在开始之前,请确保服务器满足以下前提条件:
.拓扑中的所有服务器必须使用MySQL 5.7.6或更高版本。您不能在任何一台服务器上在线禁用GTID事务,除非拓扑中的所有服务器都使用此版本 。

.所有服务器都将gtid_mode设置为ON。

1.在每个从服务器上执行以下命令,如果您使用多源复制,请为每个通道执行此操作,并包含for channel channel子句:

STOP SLAVE [FOR CHANNEL 'channel'];
CHANGE MASTER TO MASTER_AUTO_POSITION = 0, MASTER_LOG_FILE = file,MASTER_LOG_POS = position [FOR CHANNEL 'channel'];
START SLAVE [FOR CHANNEL 'channel'];


mysql> stop slave for channel 'master-1';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> stop slave for channel 'master-2';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> CHANGE MASTER TO MASTER_AUTO_POSITION = 0, MASTER_LOG_FILE ='binlog.000008',MASTER_LOG_POS=194 for channel 'master-1';
Query OK, 0 rows affected (0.01 sec)

mysql> CHANGE MASTER TO MASTER_AUTO_POSITION = 0, MASTER_LOG_FILE ='binlog.000007',MASTER_LOG_POS=194 for channel 'master-2';
Query OK, 0 rows affected (0.00 sec)

mysql> start slave for channel 'master-1';
Query OK, 0 rows affected (0.00 sec)

mysql> start slave for channel 'master-2';
Query OK, 0 rows affected (0.00 sec)

2.在每个服务器上执行:

SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;

mysql> SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)

3.在每个服务器上执行:

SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;

mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
Query OK, 0 rows affected (0.03 sec)

4.在每个服务器上,等待变量@@GLOBAL。GTID_OWNED等于空字符串。可以使用以下命令检查:

mysql> SELECT @@GLOBAL.GTID_OWNED;
+---------------------+
| @@GLOBAL.GTID_OWNED |
+---------------------+
|                     |
+---------------------+
1 row in set (0.00 sec)

在复制从机上,从理论上讲,它可能是空的,然后又变为非空的。这不是问题,空一次就足够了。

5.等待当前存在于任何二进制日志中的所有事务复制到所有从属日志
1.在主服务器执行:

SHOW MASTER STATUS;

主库1:10.18.30.50

mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000010 |      194 |              |                  | bb8b95d1-6f47-11ef-9592-005056a390e6:1-10 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)


主库2:10.18.30.43

mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000009 |      194 |              |                  | 684e1f7d-6f47-11ef-a6d5-005056a3a162:1-11 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)

记下“文件和位置”列中的值

2.在每个从属服务器上,使用来自主服务器的文件和位置信息执行:

SELECT MASTER_POS_WAIT('source_log_file', source_log_pos [, timeout][, channel])

从库:10.18.30.39

mysql> SELECT MASTER_POS_WAIT('binlog.000010',194,0,'master-1');
+---------------------------------------------------+
| MASTER_POS_WAIT('binlog.000007',194,0,'master-1') |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT MASTER_POS_WAIT('binlog.000009',194,0,'master-2');
+---------------------------------------------------+
| MASTER_POS_WAIT('binlog.000006',194,0,'master-2') |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
1 row in set (0.00 sec)

返回值为0 ,代表从库已经应用了主库1binlog.000010 194与 主库2binlog.000009 194位置的数据。

如果有一个主服务器和多层的从服务器,或者换句话说,有从服务器的从服务器,那么在每层都重复第2步,从主服务器开始,然后是所有的直 接从服务器,然后是所有从服务器的从服务器,以此类推。

6.如果您将二进制日志用于复制以外的其他用途,例如执行时间点备份或恢复:请等到不需要具有GTID事务的旧二进制日志时再使用。

例如,在步骤5完成之后,可以在进行备份的服务器上执行FLUSH LOGS。然后,要么显式地进行备份,要么等待您可能设置的任何定期备份例程 的下一次迭代。

理想情况下,等待服务器清除步骤5完成时存在的所有二进制日志。还要等待步骤5之前所做的备份过期。

这是整个过程中最重要的一点。重要的是要理解,包含GTID事务的日志在下一步之后不能使用。在继续之前,必须确保GTID事务不存在于拓扑中 的任何位置。

7.在每个服务器上执行:

mysql> SET @@GLOBAL.GTID_MODE = OFF;
Query OK, 0 rows affected (0.01 sec)

8.在每个服务器上,在my.cnf文件中设置gtid-mode=OFF
如果你想设置enforce_gtid_consistency=OFF,现在就可以这样做。设置好后,你应该在你的配置文件中添加enforce_gtid_consistency=OFF。

如果您想降级到MySQL的早期版本,现在就可以这样做,使用正常的降级过程。

MySQL 5.7 启用GTID联机事务

启用GTID联机事务
如何在已经在线并使用匿名事务的服务器上启用GTID事务,以及可选的自动定位功能。此过程不需要使服务器离线,适合在生产环境中 使用。但是,如果您可以在启用GTID事务时使服务器脱机,那么处理就会更容易。

在开始安之前,请确保服务器满足以下前提条件:
.拓扑中的所有服务器必须使用MySQL 5.7.6或更高版本。您不能在任何一台服务器上在线启用GTID事务,除非拓扑中的所有服务器都使用此版本 。

.所有服务器都将gtid_mode设置为默认值OFF

启用GTID事务:
1.在每个服务器上执行:

SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN;

主库1:10.18.30.50

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN;
Query OK, 0 rows affected (0.01 sec)

主库2:10.18.30.43

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN;
Query OK, 0 rows affected (0.01 sec)

从库:10.18.30.39

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN;
Query OK, 0 rows affected (0.01 sec)

让服务器在正常工作负载下运行一段时间,并监视日志。如果此步骤导致日志中出现任何警告,请调整应用程序,使其只使用gtid兼容的特性, 而不生成任何警告。

这是重要的第一步。在进入下一步之前,必须确保错误日志中没有生成警告。

2.在每个服务器上执行:

SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;

主库1:10.18.30.50

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;
Query OK, 0 rows affected (0.00 sec)

主库2:10.18.30.43

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;
Query OK, 0 rows affected (0.00 sec)

从库:10.18.30.39

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;
Query OK, 0 rows affected (0.00 sec)

3.在每个服务器上执行:

SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;

主库1:10.18.30.50

mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)

主库2:10.18.30.43

mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)

从库:10.18.30.39

mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)

哪个服务器首先执行此语句并不重要,但重要的是,所有服务器都要在任何服务器开始下一步之前完成此步骤。

4.在每个服务器上执行:

SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;

主库1:10.18.30.50

mysql> SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)

主库2:10.18.30.43

mysql> SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)


从库:10.18.30.39

mysql> SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)

哪个服务器先执行该语句并不重要。

5.在每个服务器上,等待状态变量ONGOING_ANONYMOUS_TRANSACTION_COUNT为零。可以使用以下命令进行检查:

SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';

主库1:10.18.30.50

mysql> SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';
+-------------------------------------+-------+
| Variable_name                       | Value |
+-------------------------------------+-------+
| Ongoing_anonymous_transaction_count | 0     |
+-------------------------------------+-------+
1 row in set (0.01 sec)

主库2:10.18.30.43

mysql> SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';
+-------------------------------------+-------+
| Variable_name                       | Value |
+-------------------------------------+-------+
| Ongoing_anonymous_transaction_count | 0     |
+-------------------------------------+-------+
1 row in set (0.01 sec)

从库:10.18.30.39

mysql> SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';
+-------------------------------------+-------+
| Variable_name                       | Value |
+-------------------------------------+-------+
| Ongoing_anonymous_transaction_count | 0     |
+-------------------------------------+-------+
1 row in set (0.01 sec)

注意:在复制从机上,理论上有可能显示为零,然后再次显示为非零。这不是问题,它显示一次零就足够了。

6.等待步骤5之前生成的所有事务复制到所有服务器。您可以在不停止更新的情况下执行此操作:唯一重要的是所有匿名事务都会被复制。
1.在主服务器执行:

SHOW MASTER STATUS;

主库1:10.18.30.50

mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000007 |      194 |              |                  | bb8b95d1-6f47-11ef-9592-005056a390e6:1-10 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)


主库2:10.18.30.43

mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000006 |      194 |              |                  | 684e1f7d-6f47-11ef-a6d5-005056a3a162:1-10 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)

记下“文件和位置”列中的值

2.在每个从属服务器上,使用来自主服务器的文件和位置信息执行:

SELECT MASTER_POS_WAIT('source_log_file', source_log_pos [, timeout][, channel])

从库:10.18.30.39

mysql> SELECT MASTER_POS_WAIT('binlog.000007',194,0,'master-1');
+---------------------------------------------------+
| MASTER_POS_WAIT('binlog.000007',194,0,'master-1') |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT MASTER_POS_WAIT('binlog.000006',194,0,'master-2');
+---------------------------------------------------+
| MASTER_POS_WAIT('binlog.000006',194,0,'master-2') |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
1 row in set (0.00 sec)


mysql> SELECT MASTER_POS_WAIT('binlog.000006',195,0,'master-2');
+---------------------------------------------------+
| MASTER_POS_WAIT('binlog.000006',194,0,'master-2') |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
1 row in set (0.00 sec)

返回值为0 ,代表从库已经应用了主库1binlog.000007 194与 主库2binlog.000006 194位置的数据。

如果有一个主服务器和多层的从服务器,或者换句话说,有从服务器的从服务器,那么在每层都重复第2步,从主服务器开始,然后是所有的直 接从服务器,然后是所有从服务器的从服务器,以此类推。

如果使用循环复制拓扑,其中多个服务器可能有写客户端,则对每个主从连接执行步骤2,直到完成整个循环。重复整个过程,这样你就可以完 成整个循环两次。

例如,假设你有3个服务器A、B和C,它们在一个循环中复制A -> B -> C -> A。过程如下:

? Do step 1 on A and step 2 on B.
? Do step 1 on B and step 2 on C.
? Do step 1 on C and step 2 on A.
? Do step 1 on A and step 2 on B.
? Do step 1 on B and step 2 on C.
? Do step 1 on C and step 2 on A.

7.如果您将二进制日志用于除了复制之外的任何事情,例如时间点备份和恢复,请等待,直到您不需要具有没有gtid的事务的旧二进制日志。

例如,在步骤6完成后,可以在正在备份的服务器上执行FLUSH LOGS。然后,要么显式地进行备份,要么等待您可能设置的任何定期备份例程的 下一次迭代。理想情况下,等待服务器清除步骤6完成时存在的所有二进制日志。还要等待步骤6之前所做的备份过期。

这是第二点。理解包含匿名事务的二进制日志(没有gtid)在下一步中是无法使用的,这一点至关重要。在此步骤之后,您必须确保没有GTIDs的 事务在拓扑中不存在。

8.在每个服务器上

mysql> SET @@GLOBAL.GTID_MODE = ON;
Query OK, 0 rows affected (10.06 sec)

9.在每个服务器的my.cnf文件中加上gtid-mode=ON
现在可以保证所有的事务都有一个GTID(除了第5步或更早阶段生成的事务,它们已经被处理过)。要开始使用GTID协议以便稍后执行自动故障转 移,请在每个从服务器上执行以下操作。如果使用多源复制,可选地对每个通道执行此操作,并包括for channel channel子句:

STOP SLAVE [FOR CHANNEL 'channel'];
CHANGE MASTER TO MASTER_AUTO_POSITION = 1 [FOR CHANNEL 'channel'];
START SLAVE [FOR CHANNEL 'channel'];


mysql> stop slave for channel 'master-1';
Query OK, 0 rows affected (0.02 sec)

mysql> stop slave for channel 'master-2';
Query OK, 0 rows affected (0.01 sec)

mysql> CHANGE MASTER TO MASTER_AUTO_POSITION = 1 for channel 'master-1';
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_AUTO_POSITION = 1 for channel 'master-2';
Query OK, 0 rows affected (0.00 sec)

mysql> start slave for channel 'master-1';
Query OK, 0 rows affected (0.01 sec)

mysql> start slave for channel 'master-2';
Query OK, 0 rows affected (0.00 sec)