gtid

网友投稿 754 2022-09-01

gtid

gtid

gtid知识:

一、gtid持久化介质

01 、mysql.gtid_executed表:

work@master (mysql) > show create table gtid_executed\G;*************************** 1. row *************************** Table: gtid_executedCreate Table: CREATE TABLE `gtid_executed` ( `source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.', `interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.', `interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.', PRIMARY KEY (`source_uuid`,`interval_start`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 STATS_PERSISTENT=01 row in set (0.07 sec)ERROR: No query specifiedMon May 11 16:56:12 2020

02、binlog中的gtid_event

# at 120#151222 9:07:58 server id 1026872634 end_log_pos 247 CRC32 0xedf993a8 Previous-GTIDs# b3485508-883f-11e5-85fb-e41f136aba3e:1-14,# b694c8b2-883f-11e5-85fb-e41f136aba3e:1-10115960:12000000-12000005# at 247#151222 9:08:03 server id 1026872625 end_log_pos 295 CRC32 0xc3d3d8ee GTID [ commit =yes]SET @@SESSION.GTID_NEXT= 'b694c8b2-883f-11e5-85fb-e41f136aba3e:10115961' /*!*/;# at 295#151222 9:08:03 server id 1026872625 end_log_pos 370 CRC32 0x0a32d229 Query thread_id=18 exec_time=1 error_code=0BEGIN/*!*/;# at 370#151222 9:08:03 server id 1026872625 end_log_pos 480 CRC32 0x3c0e094f Query thread_id=18 exec_time=1 error_code=0use `db`/*!*/;SET TIMESTAMP =1450746483/*!*/;update tb set val = val + 1 where id = 1/*!*/;# at 480#151222 9:08:03 server id 1026872625 end_log_pos 511 CRC32 0x5772f16b Xid = 6813913COMMIT /*!*/;# at 511#151222 9:10:19 server id 1026872625 end_log_pos 559 CRC32 0x3ac30191 GTID [ commit =yes]SET @@SESSION.GTID_NEXT= 'b694c8b2-883f-11e5-85fb-e41f136aba3e:10115962' /*!*/;# at 559#151222 9:10:19 server id 1026872625 end_log_pos 634 CRC32 0x83a74912 Query thread_id=18 exec_time=0 error_code=0SET TIMESTAMP =1450746619/*!*/;BEGIN/*!*/;# at 634#151222 9:10:19 server id 1026872625 end_log_pos 744 CRC32 0x581f6031 Query thread_id=18 exec_time=0 error_code=0SET TIMESTAMP =1450746619/*!*/;update tb set val = val + 1 where id = 1/*!*/;# at 744#151222 9:10:19 server id 1026872625 end_log_pos 775 CRC32 0x793f8e34 Xid = 6813916COMMIT /*!*/;

二、gtid相关变量和表

01、mysql.gtid_executed表

表中。只有从库在binlog或log_slave_updates至少一个关闭时,才会实时更新的。

1. 执行 reset master 时,则删除该表所有记录。2. 执行 set global gitd_purged='' 时,则插入对应的记录到mysql.gtid_executed表,且同时更新gtid_executed为和gtid_purged相同的值,即始终保持gtid_purged是gtid_executed的子集。3. 主库:若binlog关闭,则不更新;若binlog打开,则binlog发生rotate切换时,会更新该表数据。4. 从库:若binlog或log_slave_updates至少一个关闭,则实时更新;若binlog和log_slave_updates都开启,则binlog发生rotate切换时,会更新该表数据。

02、gtid_executed变量

含义:数据库已经执行了哪些Gtid事物,存储在内存中。

show slave status中的Executed_Gtid_Set也取自这里。

gtid_executed为空有两种情况:一是执行reset master;二是之前没有启动过基于GTID的复制。

1. 执行 reset master 时,则该变量设置为空。2. 执行 set global gitd_purged='' 时,则插入对应的记录到mysql.gtid_executed表,且同时更新gtid_executed为和gtid_purged相同的值,即始终保持gtid_purged是gtid_executed的子集。3. mysql启动时,通过读取mysql.gtid_executed表的数据来初始化gtid_executed变量。4. 只有当主库在关闭binlog的时候,不会更新gtid_executed变量;其余情况,都会实时更新gtid_executed变量。

03、gitd_purged变量

含义:全局变量。用于记录已经被清除了的binlog事务集合,gitd_purged变量是gtid_executed变量的子集。

只有gtid_executed为空时,才能手动设置gitd_purged变量。

1. 执行 reset master 时,则该变量设置为空。2. 执行 set global gitd_purged='XXX' 时,则插入对应的记录到mysql.gtid_executed表,且同时更新gtid_executed为和gtid_purged相同的值,即始终保持gtid_purged是gtid_executed的子集。 用来来提示Mysql,哪些Gtid事务我已经执行过了。用于搭建从库时,使用极多。通常是先在从库执行:reset master;然后再在从库执行:set global gitd_purged='XXX', 注意,这里的XXX需要结合该从库Retrieved_Gtid_Set和Executed_Gtid_Set的并集,还要加上主库的Executed_Gtid_Set中存在的,但不是该主库产生的gtid,且该从库没有的gtid。 但是这样有个隐患,就是主库上有其他机器执行过的gtid而得到的数据,但是该从库却没有真正存在这些数据,而你在该从库上却设置为这些gtid事务是自己purge掉了,其实自己压根没有这些数据,这样就导致从库的数据少于主库,即丢掉了数据。3. mysql启动时,通过读取mysql.gtid_executed表的数据来初始化gtid_executed变量。4. 主库:若binlog关闭,则不更新gitd_purged变量;若binlog打开,则binlog被清理时,会更新gitd_purged变量。5. 从库:若binlog或log_slave_updates至少一个关闭,则实时更新gitd_purged变量;若binlog和log_slave_updates都开启,则binlog被清理时,会更新gitd_purged变量。########################################################################################################################################################################################手动删除binlog: show binary logs; purge binary logs to 'mysql-bin.000046'; purge binary logs before '2020-10-10 10:10:10';自动删除binlog: expire_logs_days时间到了,执行binlog删除

跳过gtid事务:

(1)停止复制: stop slave;(2)重置master: reset master;(3)设置gtid_purged变量: set global gtid_purged='XXX';(4)开启复制:

3,使用空事务处理故障情况1:主键重复# Last_Error: Could not execute Write_rows event on table test.a; Duplicate entry '500' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql.000005, end_log_pos 651107# 方法1:# 注入空事务 Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 7abe211e-fb4f-11e7-b16e-000c29ba88ca:66253-68381:69091-70362 Executed_Gtid_Set: 7abe211e-fb4f-11e7-b16e-000c29ba88ca:1-70362,9a455b69-fb4f-11e7-b993-000c29e8a43c:1####################################################(root@Slave)[tempdb]>stop slave sql_thread;(root@Slave)[tempdb]>set gtid_next='7abe211e-fb4f-11e7-b16e-000c29ba88ca:70363';(root@Slave)[tempdb]>begin;commit;(root@Slave)[tempdb]>set gtid_next='AUTOMATIC';(root@Slave)[tempdb]>start slave sql_thread;(root@Slave)[tempdb]>show slave status \G

04、Executed_Gtid_Set

含义:

1. 在主库中,执行 show master status命令,所得Executed_Gtid_Set,就是和全局变量gitd_executed相同值,任何时候,两者完全相同值。2. 在从库中,执行 show slave status命令,所得Executed_Gtid_Set,就是和全局变量gitd_executed相同值,任何时候,两者完全相同值。

05、Retrieved_Gtid_Set

含义:仅在从库中才有,在主库中不存在。

06、Previous-GTIDs

1. Previous_gtid_log_event在每个binlog 头部都会有每次binlog rotate的时候存储在binlog头部,Previous-GTIDs在binlog中只会存储在这台机器上执行过的所有binlog,不包括手动设置gtid_purged值。 换句话说,如果你手动set global gtid_purged=xx; 那么xx是不会记录在Previous_gtid_log_event中的。

07、gtid_next变量

跳过gtid事务:

1) 停止slave进程: mysql> stop slave; (2) 设置事务号,事务号从Retrieved_Gtid_Set获取: 在session里设置gtid_next,即跳过这个GTID mysql> SET @@sission.gtid_next= '8f9e146f-0a18-11e7-810a-0050568833c8:4' (3)设置空事物 mysql> begin; commit;(4)恢复事物号 mysql> set session gtid_next= automatic;(5) 启动slave进程 mysql>

08、gtid_owned

08、gtid_mode

09、enforce_gtid_consistency

10、gtid_executed_compression_period

1、gtid配置

关闭GTID模式。但是gtid_mode是只读的,可添加到配置文件中,然后重启mysqld来开启GTID模式。相关配置项如下:gtid-mode = ONenforce_gtid_consistency = 1log-slave-updates = 1log-bin = mysql-binlog-bin-index = mysql-bin.index

2、查看配置

> show global variables like 'gtid_%'\G;*************************** 1. row ***************************Variable_name: gtid_executed Value: 5a1a41db-9f15-11e9-a991-e4434b210720:1-2,5aa95098-9f15-11e9-98f3-e4434b5a47f8:1-429,5bcba8f5-9f15-11e9-9b14-e4434b210748:1-6319147104,5d2b585f-9f15-11e9-a58d-e4434b2106e8:1-1373519,62cdce4f-9f15-11e9-9f0d-e4434b21b430:1-2,66b80dbd-c979-11e9-8582-246e96c58570:1,85e1f282-f3a7-11e9-a222-e4434b2106e8:1-24*************************** 2. row ***************************Variable_name: gtid_executed_compression_period Value: 1000*************************** 3. row ***************************Variable_name: gtid_mode Value: ON*************************** 4. row ***************************Variable_name: gtid_owned Value:*************************** 5. row ***************************Variable_name: gtid_purged Value: 5a1a41db-9f15-11e9-a991-e4434b210720:1-2,5aa95098-9f15-11e9-98f3-e4434b5a47f8:1-429,5bcba8f5-9f15-11e9-9b14-e4434b210748:1-6047460531:6047460533,5d2b585f-9f15-11e9-a58d-e4434b2106e8:1-1373519,62cdce4f-9f15-11e9-9f0d-e4434b21b430:1-2,66b80dbd-c979-11e9-8582-246e96c58570:1,85e1f282-f3a7-11e9-a222-e4434b2106e8:1-225 rows in set (0.00 sec)ERROR:No query specifiedSun Dec 8 16:57:49 2019

这里有4个变量,其中gtid_mode已经介绍过了,其他3个变量的含义如下

gtid_executed:这既是一个Global级别的变量,又是一个Session级别的变量,是只读变量。Global级别的gtid_executed表示当前实例已经执行过的GTID集合。Session级别的gtid_executed一般情况下是空的。

gtid_owned:这既是一个Global级别的变量,又是一个Session级别的变量,是只读变量。Global级别的gtid_owned表示当前实例正在执行中的GTID,以及对应的线程id。Session级别的gtid_owned一般情况下是空的。

gtid_purged:这是一个Global级别的变量,可动态修改。我们知道binlog可以被purge掉,gtid_purged表示当前实例中已经被purge掉的GTID集合,很明显gtid_purged是gtid_executed的子集。但是gtid_purged也不是可以随意修改的,必须在@@global.gtid_executed是空的情况下,才可以动态设置gtid_purged。

binlog文件中的gtid

# at 120#151222 9:07:58 server id 1026872634 end_log_pos 247 CRC32 0xedf993a8 Previous-GTIDs# b3485508-883f-11e5-85fb-e41f136aba3e:1-14,# b694c8b2-883f-11e5-85fb-e41f136aba3e:1-10115960:12000000-12000005# at 247#151222 9:08:03 server id 1026872625 end_log_pos 295 CRC32 0xc3d3d8ee GTID [ commit =yes]SET @@SESSION.GTID_NEXT= 'b694c8b2-883f-11e5-85fb-e41f136aba3e:10115961' /*!*/;# at 295#151222 9:08:03 server id 1026872625 end_log_pos 370 CRC32 0x0a32d229 Query thread_id=18 exec_time=1 error_code=0BEGIN/*!*/;# at 370#151222 9:08:03 server id 1026872625 end_log_pos 480 CRC32 0x3c0e094f Query thread_id=18 exec_time=1 error_code=0use `db`/*!*/;SET TIMESTAMP =1450746483/*!*/;update tb set val = val + 1 where id = 1/*!*/;# at 480#151222 9:08:03 server id 1026872625 end_log_pos 511 CRC32 0x5772f16b Xid = 6813913COMMIT /*!*/;# at 511#151222 9:10:19 server id 1026872625 end_log_pos 559 CRC32 0x3ac30191 GTID [ commit =yes]SET @@SESSION.GTID_NEXT= 'b694c8b2-883f-11e5-85fb-e41f136aba3e:10115962' /*!*/;# at 559#151222 9:10:19 server id 1026872625 end_log_pos 634 CRC32 0x83a74912 Query thread_id=18 exec_time=0 error_code=0SET TIMESTAMP =1450746619/*!*/;BEGIN/*!*/;# at 634#151222 9:10:19 server id 1026872625 end_log_pos 744 CRC32 0x581f6031 Query thread_id=18 exec_time=0 error_code=0SET TIMESTAMP =1450746619/*!*/;update tb set val = val + 1 where id = 1/*!*/;# at 744#151222 9:10:19 server id 1026872625 end_log_pos 775 CRC32 0x793f8e34 Xid = 6813916COMMIT /*!*/;

这段Binlog从文件120偏移处(Format_description_log_event之后的第一个Binlog Event)开始截取。可以看到,第一个Binlog Event的类型为:Previous-GTIDs,它存在于每个binlog文件中。当开启GTID时,每个binlog文件都有且只有一个Previous-GTIDs,位置都是在Format_description_log_event之后的第一个Binlog Event处。它的含义是在当前Binlog文件之前执行过的GTID集合,可以充当索引用,使用这个Binlog Event,可以便于快速判断GTID是否位于当前binlog文件中。

下面看看gtid_purged和gtid_executed是如何构造的。MySQL在启动时打开最老的binlog文件,读取其中的Previous-GTIDs,那么就是@@global.gtid_purged。MySQL在启动时打开最新的binlog文件,读取其中的Previous-GTIDs,构造一个gtid_set,然后再遍历这个最新的binlog文件,把遇到的每个gtid都添加到gtid_set中,当文件遍历完成时,这个gtid_set就是@@global.gtid_executed。

前面说过只有在@@global.gtid_executed为空的情况下,才可以动态设置@@global.gtid_purged。因此可以通过RESET MASTER的方式来清空@@global.gtid_executed。这一点,类似Ares中的命令:set binlog_group_id=XXX, master_server_id=YYY with reset;(是会删除binlog的) 通过解析上面的binlog文件,我们也可以看到,每个事务之前,都有一个GTID_log_event,用来指定GTID的值。总体来看,一个MySQL binlog的格式大致如下:

我们知道,在未开启GTID模式的情况下,从库用(File_name和File_pos)二元组标识执行到的位置。START SLAVE时,从库会先向主库发送一个BINLOG_DUMP命令,在BINLOG_DUMP命令中指定File_name和File_pos,主库就从这个位置开始发送binlog。

在开启GTID模式的情况下,如果指定MASTER_AUTO_POSITION=1。START SLAVE时,从库会计算Retrieved_Gtid_Set和Executed_Gtid_Set的并集(通过SHOW SLAVE STATUS可以查看),然后把这个GTID并集发送给主库。主库会使用从库请求的GTID集合和自己的gtid_executed比较,把从库GTID集合里缺失的事务全都发送给从库。如果从库缺失的GTID,已经被主库pruge了呢?从库报1236错误,IO线程中断。

主库发送的二进制的事件:主库Executed_Gtid_Set对从库(Retrieved_Gtid_Set U Executed_Gtid_Set)的补集

Retrieved_Gtid_Set:从库已经接收到主库的事务编号

Executed_Gtid_Set:已经执行的事务编号

考虑下面这种情况,有个集群已经在使用GTID模式同步,想给集群增加一台从库,新做完一台从库,数据和主库一致,但是没有binlog,也就是说新从库的@@global.gtid_executed是空的。但是CHANGE MASTER时可以通过File_name和File_pos找到正确的同步点,然后START SLAVE,一切正常。过了一会儿,觉得还可以通过MASTER_AUTO_POSITION = 1的方式重新CHANGE MASTER,然后再START SLAVE。这种情况下,主库一看从库GTID里少了那么多binlog,然后把全部缺失的binglog再给从库发送一遍,那么悲剧就发生了。

为了解决这个问题,新做完从库以后,应该在从库上执行reset master; set global gtid_purged = 'xxxxx',把缺失的GTID集合设置为purged,然后就可以直接使用MASTER_AUTO_POSITION=1自动找点儿了。

由此可见,开启GTID以后,Binlog和数据文件一样重要,不仅要求主从数据一致,还要求主从Binlog中GTID集合一致。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:thinkphp5框架前后端分离项目实现分页功能的方法分析(php分页功能怎么实现)
下一篇:PHP7 安装event扩展的实现方法(PHp7.0项目部署)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~