Haohao Notes

DREAM OF TECHNICAL ACHIEVEMENT

0%

MySQL GTID详解

GTID介绍

GTID概念

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

划重点:

  1. 全局事务表示(Global Transaction ID)
  2. GTID与事务一一对应,并且全局唯一ID.
  3. 一个GTID在一个服务器上执行一次.
  4. MySQL 5.6.5开始支持GTID.

GTID特点

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

GTID组成

GTID = server_uuid:transaction+id

查看server_uuid:

1
2
3
root@a84d983d7d50:/var/lib/mysql# more auto.cnf 
[auto]
server-uuid=59fd3bd6-a6da-11ea-91d7-0242ac110003

GTID和binlog的关系

GTID和binlog的关系

GTID event 结构

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

假设有4个binlog: bin.001,bin.002,bin.003,bin.004

  • bin.001 : Previous-GTIDs=empty; binlog_event有: 1-40
  • bin.002 : Previous-GTIDs=1-40; binlog_event有: 41-80
  • bin.003 : Previous-GTIDs=1-80; binlog_event有: 81-120
  • bin.004 : Previous-GTIDs=1-120; binlog_event有: 121-160

GTID和Binlog之间的关系是怎么对应的呢? 如何才能找到GTID=? 对应的binlog文件呢?

假设现在我们要找GTID=$A,那么MySQL的扫描顺序为:

  • 从最后一个binlog开始扫描(即: bin.004)
  • bin.004的Previous-GTIDs=1-120,如果$A=140 > Previous-GTIDs,那么肯定在bin.004中
  • bin.004的Previous-GTIDs=1-120,如果$A=88 包含在Previous-GTIDs中,那么继续对比上一个binlog文件 bin.003,然后再循环前面2个步骤,直到找到为止.

GTID的复制协议

  1. 从服务器向主服务器发送已经执行过的GTID.
  2. 主服务器将所有其他GTID发送给从服务器.
  3. 同样的GTID不能被执行两次,如果有同样的GTID,会自动跳过.

COM_BINLOG_DUMP_GTID

传统复制与GTID对比