今天上午,做了一个比较有意思的操作,之前一直没有做过,就是把一套比较老的主从复制环境从基于偏移量的复制方式改为了基于GTID的复制方式,这里记录一下过程,如果大家有这方面的需求,可以参考一下:
基于偏移量的主从复制模式,需要在搭建主从复制的时候,使用参数--master-data=2来保存偏移量的位置,分别是mysqlbinlog的文件名称和binlog的log-pos位置,搭建主从的语句类似下面的方式:
change master to master_host='10.30.124.68',
master_user='dba_repl',
master_port=4306,
master_password='123456',
master_log_file='mysqlbin.000002',
master_log_pos=194;
基于GTID的方式只需要开启GTID,也就是全局事务ID,后面就可以直接使用比较简单的方式来进行复制,如下:
change master to master_host='10.30.124.186',
master_user='dba_repl',
master_password='123456',
master_port=4306,
master_auto_position=1;
很明显,第二种方法简单多了,不用关心当前的binlog应用到的位置。
那么我们如何将第一种复制方式转换到第二种复制方式呢?这个问题可能也要分两种情况:
第一种情况是业务没有什么数据写入,那么你完全可以停服维护,重新修改my.cnf里面的参数,在重新启动实例,这是没有问题的。事实上,老版本的MySQL也只能使用这种方式。
第二种就是在线维护了,就是上面还有业务,那么想要直接切换,就没有那么容易了,需要做的事情就比较多一点,不过也是可以的。在MySQL5.7之后,可以支持在线修改。下面我们举例说明,假如我们的IP地址分别如下:
10.30.124.68 主节点
10.30.124.128 从节点
首先需要明确的是,直接修改复制方式是不行的,如下:
mysql--dba_admin@127.0.0.1:(none) 15:40:38>>
change master to master_host='10.30.124.128',
-> master_user='dba_repl',
-> master_password='replsafe',
-> master_port=,
-> master_auto_position=;
ERROR 1777 (HY000): CHANGE MASTER TO MASTER_AUTO_POSITION = cannot be executed because @@GLOBAL.GTID_MODE = OFF.
报错,提示我们需要将gtid_mode设置为on,我们查看下当前的gtid的参数:
mysql--15:40:49>>show variables like '%gtid%';
+----------------------------------+-------------------------------------------+
| Variable_name | Value |
+----------------------------------+-------------------------------------------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | OFF |
| gtid_executed_compression_period | 1000 |
| gtid_mode | OFF |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | a26a43c3-fd2f-11e8-9b10-005056b7c285:1-45 |
| session_track_gtids | OFF |
+----------------------------------+-------------------------------------------+
8 rows in set (0.00 sec)
可以看到gtid_mode是关闭的,如果你想直接设置这个gtid_mode的值,那也是会报错:
mysql-- ::>>set global gtid_mode='on';
ERROR (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.
这个提示的内容中可以看到,这个参数gtid_mode是一个单项的修改过程,也就是说从off到on,需要经过中间的OFF <-> OFF_PERMISSIVE <-> ON_PERMISSIVE <-> ON
过程,而相邻的两个状态之间可以相互转换。否则会出错。
在整个切换的过程中,需要注意两个参数:
第一个是gtid_mode参数那四个状态的含义在官方文档中的描述如下:
MySQL 5.7.6及更高版本中记录的事务可以是匿名的,也可以使用GTID。匿名事务依赖于二进制日志文件和位置来标识特定事务。GTID事务具有用于引用事务的唯一标识符。MySQL 5.7.6中添加的 OFF_PERMISSIVE
和 ON_PERMISSIVE
模式允许在拓扑中混合使用这些事务类型。现在有不同的模式:
OFF
:新事务和复制事务都必须是匿名的。OFF_PERMISSIVE
:新交易是匿名的。复制的事务可以是匿名或GTID事务。ON_PERMISSIVE
:新交易是GTID交易。复制的事务可以是匿名或GTID事务。ON
:新事务和复制事务都必须是GTID事务。从一个值到另一个值的变化一次只能是一步。例如,如果 gtid_mode
当前设置为OFF_PERMISSIVE
,则可以更改为OFF
或 ON_PERMISSIVE
不更改 ON
。
第二个是enforce_gtid_consistency,它的含义在官方文档中如下:
enforce_gtid_consistency
可以配置 的值 是:
OFF
:允许所有交易违反GTID一致性。ON
:不允许任何交易违反GTID一致性。WARN
:允许所有事务违反GTID一致性,但在这种情况下会生成警告。WARN
在MySQL 5.7.6中添加了。enforce_gtid_consistency
仅在语句进行二进制日志记录时才生效。如果在服务器上禁用了二进制日志记录,或者由于过滤器删除了语句而未将语句写入二进制日志,则不会对未记录的语句检查或强制执行GTID一致性。
综上所述,正确的步骤大概如下:
1、在每一台服务器上面设置enforce_gtid_consistency=warn,这个参数可以使得所有事物都允许违反GTID的一致性,但是会生成警告,通过这个方法,把那些不符合GTID一致性的事务给找出来,并修复。
2、在每一台服务器上设置enforce_gtid_consistency=on,这一步操作需要在处理完上面一步操作的基础上执行,从而确保所有的事务都不能违反GTID的一致性。
3、在每一台服务器上设置gtid_mode=off_permissive,这一步表示新的事务是匿名的,同时允许复制的事务为GTID或者匿名事务
4、在每一台服务器上设置gtid_mode=on_permissive,这一步表示新的事务使用gtid,同时允许复制的事务为GTID或者匿名事务
5、等待ongoing_anonymous_transaction_count的状态值为0,可以使用show status like这个参数的方法在所有的从库上查询该状态,必须要为0才能开始下一步。这个状态位表示的是已经标记为匿名的正在进行的事务数量,如果状态值为0,说明当前没有事务在等待被处理。如果这个值没有为0就开始操作,就会犯和我一样的错误,就是报错,如下:
-08-01T07::24.539854Z [ERROR] Error reading packet from server for
channel '': Cannot replicate anonymous transaction when AUTO_POSITION = 1,
at file /data/mysql_4306/innodblog/mysqlbin.000007, position 234.; the
first event '' at 4, the last event read from '/data/mysql_4306/innodblog
/mysqlbin.000007' at 299, the last byte read from '/data/mysql_4306/innodblog
/mysqlbin.000007' at 299. (server_errno=1236)
-08-01T07::24.539878Z [ERROR] Slave I/O for channel '': Got fatal
error from master when reading data from binary log: 'Cannot replicate
anonymous transaction when AUTO_POSITION = , at file /data/mysql_4306/
innodblog/mysqlbin.000007, position 234.; the first event '' at 4, the
last event read from '/data/mysql_4306/innodblog/mysqlbin.000007' at 299,
the last byte read from '/data/mysql_4306/innodblog/mysqlbin.000007' at 299.',
Error_code:
6、在每一台服务上设置gtid_mode=on,开启GTID
7、修改my.cnf中的参数,设置gtid_mode=on,设置enforce_gtid_consistency的值为1,这样保证数据库如果重启,这个gtid的设置也是生效的。
8、做完这些操作之后,需要做的是重新stop slave,然后使用master_auto_postion=1的方法将复制调整为GTID的模式。