1.GTID基本概念
传统的基于binlog position复制的方式有个严重的缺点:如果slave连接master时指定的binlog文件错误或者position错误,会造成遗漏或者重复,很多时候前后数据是有依赖性的,这样就会出错而导致数据不一致。
GTID的全称是global transaction id,mysql5.6开始支持,表示全局事务ID
分配方式:
uuid:trans_id
uuid是每个mysql服务器都唯一的,记录在$datadir/auto.cnf中。如果复制结构中,任意两台服务器uuid重复的话(比如直接冷备份时,auto.conf中的内容是一致的),在启动复制功能的时候会报错。这时可以删除auto.conf文件再重启mysqld。
(admin@g1-db-test:6005)[(none)]>select @@server_uuid;
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| b3f6377f-52c5-11ea-92c4-be6f2b61965c |
+--------------------------------------+
(admin@g1-db-test:6005)[(none)]>show variables like '%uuid%';
+---------------+--------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------+
| server_uuid | b3f6377f-52c5-11ea-92c4-be6f2b61965c |
+---------------+--------------------------------------+
trans_id是事务ID,可以唯一标记某MySQL服务器上执行的某个事务。事务号从1开始,每提交一个事务,事务号加1。
例如"gtid_executed 5ad9cb8e-2092-11e7-ac95-000c29bf823d:1-6",表示该server_uuid上执行了从1到6的事务
2.GTID的生命周期
GTID如何持久化
gtid在master和slave上是一直持久化保存(即使删除了日志,也会记录到Previous_GTID中)的。它在master和slave上的生命周期如下:
1.master产生GTID
客户端发送DDL/DML给master上,master首先对此事务生成一个唯一的gtid,假如为uuid_xxx:1,然后立即执行该事务中的操作。
注意,主从复制的情况下,sync-binlog基本上都会设置为1,这表示在每次提交事务时将缓存中的binlog刷盘。所以,在事务提交前,gtid以及事务相关操作的信息都在缓存中,提交后它们才写入到binlog file中,然后才会被dump线程dump出去。
换句话说,只有提交了的事务,gtid和对应的事务操作才会记录到binlog文件中。记录的格式是先记录gtid,紧跟着再记录事务相关的操作。
2.将binlog发送到slave
将binlog发送到slave所在服务器,并存储到relay log,slave读取GTID,并设置变量 gtid_next 的值为该gtid,表示下一个要操作的事务是该gtid。 gtid_next 是基于会话的,不同会话的gtid_next不同。
3.slave执行GTID
随后slave检测该gtid在自己的binlog中是否存在。如果存在,则放弃此gtid事务;如果不存在,则将此gtid写入到自己的binlog中,然后立刻执行该事务,并在自己的binlog中记录该事务相关的操作。
注意,slave上replay的时候,gtid不是提交后才写到自己的binlog file的,而是判断gtid不存在后立即写入binlog file。
通过这种在执行事务前先检查并写gtid到binlog的机制,不仅可以保证当前会话在此之前没有执行过该事务,还能保证没有其他会话读取了该gtid却没有提交。因为如果其他会话读取了该gtid会立即写入到binlog(不管是否已经开始执行事务),所以当前会话总能读取到binlog中的该gtid,于是当前会话就会放弃该事务。总之,一个gtid事务是决不允许多次执行、多个会话并行执行的。
4.slave不生成GTID
slave在重放relay log中的事务时,不会自己生成gtid,所以所有的slave(无论是何种方式的一主一从或一主多从复制架构)通过重放relay log中事务获取的gtid都来源于master,并永久保存在slave上。
3.GTID的好处
保证同一个事务在某slave上绝对只执行一次,没有执行过的gtid事务总是会被执行。
不用像传统复制那样保证binlog的坐标准确,因为根本不需要binlog以及坐标。
故障转移到新的master的时候很方便,简化了很多任务。
很容易判断master和slave的数据是否一致。只要master上提交的事务在slave上也提交了,那么一定是一致的。
当然,MySQL提供了选项可以控制跳过某些gtid事务,防止slave第一次启动复制时执行master上的所有事务而导致耗时过久。
虽然对于row-based和statement-based的格式都能进行gtid复制,但建议采用row-based格式。
4.GTID配置
master配置文件
[mysqld]
datadir=/data
socket=/data/mysql.sock
log-bin=/data/master-bin #