mysql-server-5.7.6+ 在线开启gtid与在线关闭gtid
#################################################
声明:在线开启gtid是有挂库风险的:因为我和同事均遇到过。
#################################################
在开始之前,请确保服务器满足以下先决条件:
-
所有服务器都
gtid_mode
设置为默认值OFF
。
-
拓扑中的所有服务器都必须使用 MySQL 5.7.6+。 除非拓扑中的 所有服务器都使用此版本,否则您不能在任何单个服务器上在线启用 GTID 事务
主库:192.168.225.128:3307
从库1:192.168.225.129:3307
Gtid作为5.6版本以来的杀手级特性,却因为不支持拓扑结构内开关而饱受诟病。如果你需要从未开启GTID的环境升级到开启GTID,需要把这个复制结构里的实例shutdown后,再重启。相信这对于任何24小时服务的互联网应用都是不可接受的。
https://blog.csdn.net/wanbin6470398/article/details/83068044#15__88
master_auto_position=0 表示禁用master_auto_position
SET @@global.enforce_gtid_consistency=warn;
SET @@global.enforce_gtid_consistency=ON;
SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;
SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';
SELECT MASTER_POS_WAIT('mysql-bin6.000006', 154);
SET @@GLOBAL.GTID_MODE = ON;
STOP SLAVE;
CHANGE MASTER TO master_auto_position=1;
START SLAVE;
OFF
|
彻底关闭GTID,如果关闭状态的备库接受到带GTID的事务,则复制中断
|
OFF_PERMISSIVE
|
可以认为是关闭GTID前的过渡阶段,主库在设置成该值后不再生成GTID,备库在接受到带GTID 和不带GTID的事务都可以容忍
主库在关闭GTID时,执行事务会产生一个Anonymous_Gtid事件,会在备库执行:
SET @@SESSION.GTID_NEXT= ‘ANONYMOUS’
备库在执行匿名事务时,就不会去尝试生成本地GTID了
|
ON_PERMISSIVE
|
可以认为是打开GTID前的过渡阶段,主库在设置成该值后会产生GTID,同时备库依然容忍带GTID和不带GTID的事务
|
ON
|
完全打开GTID,如果打开状态的备库接受到不带GTID的事务,则复制中断
|
主从复制传统复制已配置完毕
一、前提:
1.要求所有的mysql版本5.7.6或更高的版本。
2.目前拓扑结构中所有的mysql的gtid_mode的值为off状态。
3.如下的操作步骤都是有序的,不要跳跃着进行。
补充一下全局系统变量GTID_MODE变量值说明:
OFF 新事务是非GTID, Slave只接受不带GTID的事务,传送来GTID的事务会报错
OFF_PERMISSIVE 新事务是非GTID, Slave即接受不带GTID的事务也接受带GTID的事务
ON_PERMISSIVE 新事务是GTID, Slave即接受不带GTID的事务也接受带GTID的事务
ON 新事务是GTID, Slave只接受带GTID的事务
需要注意的是,这几个值的改变是有顺序的,即
off<--->OFF_PERMISSIVE<--->ON_PERMISSIVE<--->ON
不能跳跃执行,会报错。
二、传统复制切换为GTID复制
前提:测试步骤中S1默认都是打开log-bin选项的,
操作步骤
1. 在M、S实例上,将ENFORCE_GTID_CONSISTENCY设置为warning,哪台先执行不影响结果
M:mysql> set @@global.enforce_gtid_consistency=warn;
S:mysql> set @@global.enforce_gtid_consistency=warn;
注意:执行完这条语句后,如果出现GTID不兼容的语句用法,在错误日志会记录相关信息,那么需要调整应该程序避免不兼容的写法,直到完全没有产生不兼容的语句,可以通过应该程序去排查所有的sql,也可以设置后观察错误日志一段时间,这一步非常重要。
这是重要的第一步。在进行下一步之前,您必须确保错误日志中没有生成任何警告。
2. 在M、S上,设置ENFORCE_GTID_CONSISTENCY为ON,哪台先执行不影响结果
M:mysql> set @@global.enforce_gtid_consistency=on;
S:mysql> set @@global.enforce_gtid_consistency=on;
3. 在M、S实例上,设置GTID_MODE为off_permissiv;哪台先执行不影响结果
M:mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
S:mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
哪个服务器先执行这个语句并不重要,重要的是所有服务器在任何服务器开始下一步之前完成这个步骤。
4. 在M、S实例上,设置GTID_MODE为on_permissiv;哪台先执行不影响结果
M: Mysql> SET @@GLOBAL.GTID_MODE = on_permissive;
S: Mysql> SET @@GLOBAL.GTID_MODE = on_permissive;
哪个服务器先执行这个语句并不重要,重要的是所有服务器在任何服务器开始下一步之前完成这个步骤。
5. 在M、S上检查变量ONGOING_ANONYMOUS_TRANSACTION_COUNT,需要等到此变量为0,在每台服务器上,等待状态变量 ONGOING_ANONYMOUS_TRANSACTION_COUNT
为零。这可以使用以下方法检查:
Mysql> SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';
Mysql> SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';
在副本上,理论上可能显示为零,然后再次显示为非零。这不是问题,它显示一次零就足够了。
等待直到第 5 步生成的所有事务复制到所有服务器。您可以在不停止更新的情况下执行此操作:唯一重要的是所有匿名事务都会被复制。
有关检查所有匿名事务是否已复制到所有服务器的一种方法, 请参见 第 16.1.4.4 节,“验证匿名事务的复制” 。
如果您将二进制日志用于除复制之外的任何其他用途,例如时间点备份和恢复,请等到您不需要旧的二进制日志具有没有 GTID 的事务。
例如,在第 6 步完成后,您可以 FLUSH LOGS
在要进行备份的服务器上执行。然后明确地进行备份或等待您可能已设置的任何定期备份例程的下一次迭代。
理想情况下,等待服务器清除在第 6 步完成时存在的所有二进制日志。还要等待在第 6 步之前进行的任何备份过期。
这是第二个重点。重要的是要了解包含匿名事务的二进制日志,没有 GTIDs 不能在下一步之后使用。在此步骤之后,您必须确保没有 GTID 的事务不存在于拓扑中的任何位置。
6. 确保所有的匿名事务(非GTID事务)已经被完全复制到所有的server上。
M:show master status;
S:show slave status\G
或者或者slave直接用函数:
SELECT MASTER_POS_WAIT('mysql-binlog.000005',154);
返回结果大于等于0就说明匿名事务已经全部复制完成
7. 确认整个拓扑结构中已经没有匿名事务的存在,
如之前产生的所有匿名事务已经全部被执行完毕,甚至二进制日志中也不要有匿名事务,可以通过flush logs,并让mysql来自动清理旧的二进制日志文件。
8. 在每个mysql实例上,设置GTID_MODE为on
M: mysql> SET @@GLOBAL.GTID_MODE = ON;
S: mysql> SET @@GLOBAL.GTID_MODE = ON;
9. 在每个mysql实例的配置文件my.cnf上,在每台服务器上,添加gtid_mode=ON
和 enforce_gtid_consistency=ON
到 my.cnf
.
增加: SHOW VARIABLES LIKE '%gtid%';
gtid_mode=ON
enforce_gtid_consistency=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'];
10. 每个从库开启master_auto_position
这个步骤需要特别注意,对比下从库的Retrieved_Gtid_Set与Executed_Gtid_Set的并集和主库的Executed_Gtid_Set。
2.9 change master
root@localhost [(none)] 11:37:17>STOP slave;
Query OK, 0 rows affected (0.00 sec)
root@localhost [(none)] 11:37:24>change master to master_auto_position=1;
Query OK, 0 rows affected (0.00 sec)
root@localhost [(none)] 11:37:52>start slave;
Query OK, 0 rows affected (0.00 sec)
##############################################
如果报错,请按照下面执行:
stop slave;
reset slave;
reset master;
该值=从库接受到的gtid集合 Retrieved_Gtid_Set+主库产生Executed_Gtid_Set的但从库没有的,
# 从库的Retrieved_Gtid_Set往往和Executed_Gtid_Set的值是一样的。取两者的并集:Retrieved_Gtid_Set U Executed_Gtid_Set
SET @@GLOBAL.GTID_PURGED='12a62f29-e0dc-11e9-9d20-00163e00248a:1-22470,947b2801-e0ed-11e9-aefb-00163e00248a:1';
#####主库:
master@10.10.10.10((none)) > show master status\G; *************************** 1. row *************************** File: mysql-bin.005702 Position: 900958585 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 12a62f29-e0dc-11e9-9d20-00163e00248a:1-22047, 947b2801-e0ed-11e9-aefb-00163e00248a:1 1 row in set (0.07 sec) ERROR: No query specified Mon May 11 16:00:51 2020 ###########从库: slave@10.10.10.11 ((none)) > show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.10.10.10 Master_User: mysqlsync Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.005703 Read_Master_Log_Pos: 140353981 Relay_Log_File: relay-bin.000004 Relay_Log_Pos: 140354146 Relay_Master_Log_File: mysql-bin.005703 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 140353981 Relay_Log_Space: 140354422 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 171574486 Master_UUID: 12a62f29-e0dc-11e9-9d20-00163e00248a Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 12a62f29-e0dc-11e9-9d20-00163e00248a:21547-22470 Executed_Gtid_Set: 12a62f29-e0dc-11e9-9d20-00163e00248a:1-22470, 947b2801-e0ed-11e9-aefb-00163e00248a:1 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.07 sec) ERROR: No query specified
my.cnf 配置:
log_bin = mysql-bin
bin_log = /usr/local/mysql/log/mysql-bin
binlog_format = ROW //建议row
log-slave-updates=true //在从服务器进入主服务器传入过来的修改日志所使用,在Mysql5.7之前主从架构上使用gtid模式的话,必须使用此选项,在Mysql5.7取消了,会增加系统负载。
enforce-gtid-consistency=true // 强制gtid一直性,用于保证启动gitd后事务的安全;
gtid-mode=on //开启gtid模式
master_info_repository=TABLE
relay_log_info_repository=TABLE //指定中继日志的存储方式,默认是文件,这样配置是使用了 两个表,是INNODB存储引擎,好处是当出现数据库崩溃时,利用INNODE事务引擎的特点,对这两个表进行恢复,以保证从服务器可以从正确位置恢复数据。
sync-master-info=1 //同步master_info,任何事物提交以后都必须要把事务提交以后的二进制日志事件的位置对应的文件名称,记录到master_info中,下次启动自动读取,保证数据无丢失
slave-parallel-workers=2 //设定从服务器的启动线程数,0表示不启动
binlog-checksum=CRC32 //主服务端在启动的时候要不要校验bin-log本身的校验码
master-verify-checksum=1 //都是在服务器出现故障情况下,读取对服务器有用的数据
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1 //启用后,可用于在二进制日志记录事件相关信息,可降低故障排除复杂度(并非强制启动)
使用基于GTID的复制时(MASTER_AUTO_POSITION = 1),首先要开启gtid_mode(在my.cnf中设置gtid-mode = ON),MASTER_LOG_FILE 与 MASTER_LOG_POS也不能使用,否则会报错。 使用GTID后想要恢复到老的基于文件的复制协议,在change master to时需要指定MASTER_AUTO_POSITION = 0以及MASTER_LOG_FILE 或 MASTER_LOG_POSITION中至少一项。
参考:
https://dev.mysql.com/doc/refman/5.7/en/replication-mode-change-online-enable-gtids.html
###################