MySQL GTID

MySQL GTID简介

GTID( Global Transaction Identifier)全局事务标识,由主库上生成的与事务绑定的唯一标识,这个标识不仅在主库上是唯一的,在MySQL集群内也是唯一的。GTID是 MySQL 5.6 版本引入的一个有关于主从复制的重大改进,相对于之前版本基于Binlog文件+Position的主从复制,基于GTID的主从复制,数据一致性更高,主从数据复制更健壮,主从切换、故障切换不易出错,很少需要人为介入处理。

MySQL GTID特点

事务提交产生GTID,GTID与事务及事务提交所在的节点绑定,GTID与事务一起写入Binlog,但是从库应用Binlog并不会生成新的GTID。集群中的任何一个节点,根据其GTID值就可以知道哪些事务已经执行,哪些事务没有执行,如果发现某个GTID已执行,重复执行该GTID,将会被忽略,即同一个GTID只能被应用一次。当一个连接执行一个特定GTID的事务,但是还没有提交,此时有另外一个连接也要执行相同GTID的事务,那么第二个连接的执行将会被阻塞,直到第一个事务提交或者回滚。如果第一个事务成功提交,第二个事务将会被忽略。如果第一个事务回滚,第二个事务正常执行。如何开启GTID

gtid_mode=ON

enforce_gtid_consistency=ON

GTID长啥样

GTID = server_uuid:transaction_id

示例:3E11FA47-71CA-11E1-9E33-C80AA9429562:1

server_uuid标识了该事务执行的源节点,存储在数据目录中的auto.cnf文件中,transaction_id 是在该主库上生成的事务序列号,从1开始,示例中 3E11FA47-71CA-11E1-9E33-C80AA9429562 是这个节点的server_uuid,1为这个节点上提交的第1个事务的事务号,如果提交了10个事务,GTID会是这样: 3E11FA47-71CA-11E1-9E33-C80AA9429562:1-10

GTID可以是一段连续或者不连续的几段事务序列集合,下面是可能出现的GTID模样:

3E11FA47-71CA-11E1-9E33-C80AA9429562:1

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3:12:47-49

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19(多个节点提交事务,通常发生了主从切换)

GTID存储在什么地方?

GTID与事务绑定在一起,随着事务的提交,GTID随事务信息一起写入Binlog,通过主从复制,传递到从库。对于已经执行了的事务,其GTID通常会记录在MySQL的系统变量@@GLOBAL.gtid_executed 以及系统表mysql.gtid_executed中,系统变量@@GLOBAL.gtid_executed 在内存中,属于非持久化存储,而系统表mysql.gtid_executed属于持久化存储。

mysql.gtid_executed 表的更新。与Binlog有没有打开有关。

如果开启了Binlog,只有在 Binlog轮转或者MySQL关闭的时候,才会把Binlog中的GTID与入到mysql.gtid_executed表中。

如果没有开启Binlog,那么将通过 gtid_executed_compression_period 这个参数控制mysql.gtid_executed表的更新。默认值为1000,即每1000个事务,将mysql.gtid_executed表中的数据进行合并。 gtid_executed_compression_period设置为0,将不会进行合并,mysql.gtid_executed 表会变得越来越大,直到把磁盘用完。如果开启了Binlog,gtid_executed_compression_period这个参数将不再起作用。mysql.gtid_executed表的数据合并压缩由线程函数compress_gtid_table来执行,位于源码sql/rpl_gtid_persist.cc

extern "C" void *compress_gtid_table(void *p_thd);

该线程不在show processlist中展示,但是可以在 performance_schema.threads 表中看到。

SELECT * FROM performance_schema.threads WHERE NAME LIKE '%gtid%'\G

如果MySQL异常崩溃,GTID没来得及写入mysql.gtid_executed表中,那么在MySQL重新启动后,会从Binlog中搜索GTID,并将这一部分没有写入到mysql.gtid_executed表的GTID写入到表中。如果想查询最新的GTID提交情况,建议查询MySQL全局变量 @@GLOBAL.gtid_executed,而不是查询表 mysql.gtid_executed。

开始GTID后,Binlog存储事务和GTID信息,可以通过mysqlbinlog工具来解析,具体用法如下:

mysqlbinlog --start-datetime="2017-03-21 10:20:00" --start-datetime="2017-03-21 12:20:00" mysql-bin.000001 --base64-output=decode-rows -vvv > binlog.txt

GTID生命周期:

当一个事务在一个主库上被执行和提交,那么这个事务就会被分配一个和该主库uuid相关联的gtid,这个gtid被写入到主库的binlog文件中。当这个binlog文件达到最大值发生轮转,或者MySQL Server关闭时,上一个binlog文件中的事务GTID将会被写入到mysql.gtid_executed表中。事务提交时,该事务的gtid会很快的添加到系统变量 @@GLOBAL.gtid_executed,但是系统表 mysql.gtid_executed 则不会,因为有部分gtid还在binlog中,需要等到binlog轮转或者MySQL Server关闭时才会写入到mysql.gtid_executed表中。主库上的binlog通过主从复制协议传送到从库,并写入到从库的relay log,从库读取relay log中的gtid和对应的事务信息,把gtid_next设置为该gtid值,使得从库使用该gtid值应用其对应的事务。如果多个线程并发地应用同一个事物,比如多个线程设置gtid_next为同一个值,MySQL Server只允许其中一个线程执行,gtid_owned系统变量记录着谁拥有该GTID。GTID Auto-Position:

GTID之前的主从复制是基于文件+偏移的方式,建立主从复制,必须先知道主库的binlog文件和偏移位置( MASTER_LOG_FILE 和 MASTER_LOG_POS)。而使用基于GTID的主从复制,设置 MASTER_AUTO_POSITION =1,从库发送自身已经接收到的gtid给主库,主库将从库缺失的gtid及其对应的binlog文件发送给从库,也就是主库只发送从库没有接收到的事务。所有的信息由MySQL集群自动获取完成,不需要人为干预,大大简化了复制搭建过程。

如果主库要发送给从库的GTID所在的binlog已经被清除了,或者这些gtid已经被添加到gtid_purged,那么主库将发送错误信息给从库,复制将会中断。通常发生这种情况时,从库可以更换复制源,或者使用最新的备份来重建复制。也可以考虑修改增加主库binlog文件的过期时间来减少这种情况的发生。

如果从库已经接收到的gtid 比主库的gtid要多,那么主库也将发送错误信息给从库,同时复制中断。这种情况一般是主库没有设置 sync_binlog=1 ,此时主库发生断电、宕机等故障,导致主库的binlog没有刷到磁盘,而从库已经接收到了主库的binlog。这种情况一般需要人工介入解决,所以推荐更安全的sync_binlog=1 。

基于GTID的复制搭建:

CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=3306,MASTER_USER='repl', MASTER_PASSWORD='123456',MASTER_AUTO_POSITION=1;

基于Binlog+Position的复制搭建:

CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=524;

GTID相关函数:

GTID_SUBSET(set1,set2)

如果set1是set2的子集,返回true,否则返回false

GTID_SUBTRACT(set1,set2)

返回set1与set2的差集,即GTID在set1中,不在set2中。

WAIT_FOR_EXECUTED_GTID_SET(gtid_set[, timeout])

等待GTID执行到某一个位置,如果指定timeout参数,在timeout时间之内,gtid没有执行到该位置 ,则报错返回。

WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(gtid_set[, timeout][,channel])

等待复制线程(SQL_Thread)执行GTID到某一个位置,同样可以指定超时时间timeout。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容