在5.7.6之前,GTID mode只有ON 跟OFF两种模式,在5.7.6之后,增加了两种模式ON_PERMISSIVE,OFF_PERMISSIVE。这个模式是有顺序的OFF,OFF_PERMISSIVE,ON_PERMISSIVE,ON。修改gtid_mode时不能越级修改。比如当前的gtid_mode是off_permissive,可以修改为off,也可以修改为on_permissive,但是不能直接修改成on。下面是一个修改错误的例子:

  1. mysql> select @@gtid_mode;
  2. +-------------+
  3. | @@gtid_mode |
  4. +-------------+
  5. | ON |
  6. +-------------+
  7. 1 row in set (0.00 sec)
  8. mysql> set global gtid_mode=off;
  9. ERROR 1788 (HY000): The value of @@GLOBAL.GTID_MODE can only be changed one step at a time: OFF <-> OFF_PERMISSIVE <-> ON_PERMISSIVE <-> ON. Also note that this value must be stepped up or down simultaneously on all servers. See the Manual for instructions.
  10. mysql>

关于主从商不同gtid_mode的兼容性:

gtid_mode Source OFF Source OFF_PERMISSIVE Source ON_PERMISSIVE Source ON
Replica OFF Y Y N N
Replica OFF_PERMISSIVE Y Y Y* Y*
Replica ON_PERMISSIVE Y Y Y* Y*
Replica ON N N Y* Y*

N:代表不兼容
Y:代表兼容
*:代表可以使用自动定位

Online开启GTID事务

1.前提条件

1/所有的拓扑结构中的mysql都必须在5.7.6之后
2/所有的gtid_mode都必须是OFF

2.详细步骤

1/在所有服务器上执行以下语句:

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN;

设置完成之后,让服务跑一段时间,并且监控错误日志,如果有警告出现,调整你的应用直到没有警告。这是第一个重要的步骤,需要确保没有警告出现在错误日志中。

2/在所有服务器上执行以下语句:

SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;

3/在所有服务器上执行以下语句:

SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;

哪个服务器先执行不重要,重要的是需要按照步骤来执行,特别注意不能一次在一个服务器上执行多个步骤。
4/在所有服务器上执行以下语句:

SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;

5/确保每个服务器上ONGOING_ANONYMOUS_TRANSACTION_COUNT变量是0

SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';

在从库上,理论上可能出现0跟非0值,但是只要出现一次0就够了。

6/验证所有的匿名事务都已经复制到从库

最简单的方法就是等,一般从库应用日志延后多少秒,就等多少秒,或者等一天。
最安全的方法:
1.在主库上执行 SHOW MASTER STATUS; 记录File ,Position的值。
2.在从库上使用file,position的值执行 select master_pos_wait(file,position);
如果有多级从库(主-从-从…),分别在主从结构上执行STEP1,STEP2
如果拓扑结构是个闭环机构,例如(A->B->C->A),每个主从分别执行Step1,Step2,需要重复两次。

  • 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/在第六步完成之后,可以执行FLUSH LOGS然后进行备份。这一步要确保匿名事务在bin-log中不再使用。理想情况下,等到第六步完成之后,所有包含匿名事务的bin-log要被purge掉,所有包含匿名事务的备份失效再进行下一步。
这是第二个重要的步骤,要确保没有gtid的事务不再主从环境中。

8/在所有服务器上执行:

SET @@GLOBAL.GTID_MODE = ON;

9/在所有服务器上将gtid_mode=on,enforce_gtid_consistency=on加到my.cnf参数文件中
最后开始启用gtid 协议以便以后自动执行故障转移,在从库上执行下面的语句。如果有多个主库,加上for channel语句。

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

Online关闭GTID事务

1.前提条件

1/所有的拓扑结构中的mysql都必须在5.7.6之后
2/所有的gtid_mode都必须是OFF

2.详细步骤

1/在每个从库上执行以下语句,如果存在多个主库,加上for 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'];

2/在每个服务器上执行以下语句

SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;

3/在每个服务器上执行以下语句

SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;

4/等到每个服务器的GTID_OWNED都为空 ,可以用以下语句查询

SELECT @@GLOBAL.GTID_OWNED;

从库可能不是一直都是空字符串,但只要有一次是空的就行。
5/等待所有事务都复制到从库
6/如果使用bin-log来备份,需要执行flush logs,且要确保之前使用gtid的bin-log及相关备份全部清除掉。
7/在所有服务器上执行以下语句

SET @@GLOBAL.GTID_MODE = OFF;

8/将GTID_MODE=OFF记录到my.cnf文件,如果设置了enforce_gtid_consistency=off,将这句话也记录到my.cnf