GTID 生命周期和使用
概述
GTID即全局事务ID (global transaction identifier), 其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID,主要用于主从复制。
格式
GTID = source_id:transaction_id
-
source_id为服务器的uuid
-
transaction_id为在源服务器上执行事务的系列号
-
GTID可以是集合的形式,如
2174B383-5441-11E8-B90A-C80AA9429562:1-3:5-10, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19
-
gtid的生成方式通过参数gtid_next决定
-
- gtid_next=AUTOMATIC,自动分配gtid_next,是gtid_next的默认值
- gtid_next=‘’,手动指定gtid值。
需要注意,如果在原服务器上提交的事务生成的gitd集合不连续,那设置成****AUTOMATIC后,会自动补全,如:
#原状态
show master status;
>
Executed_Gtid_Set: 7232f285-783e-11ec-856c-00163e1bc22d:1-3
#手动指定gtid_next
SET @@SESSION.GTID_NEXT= '7232f285-783e-11ec-856c-00163e1bc22d:10'
#执行一个事务
insert into test01.user (name,age) values ("ttt",2);
#查看状态
show master status;
>
Executed_Gtid_Set: 7232f285-783e-11ec-856c-00163e1bc22d:1-3:10
#改成gtid_next=AUTOMATIC
#执行一个事务
insert into test01.user (name,age) values ("ttt",2);
#查看状态
show master status;
>
Executed_Gtid_Set: 7232f285-783e-11ec-856c-00163e1bc22d:1-4:10
涉及mysql变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cLQ1soaw-1658473572291)(https://gitee.com/leo_anna/image/raw/master/img//202201281442487.png)]
- 查看变量,select @@global.gtid_executed\G;
- gtid_purged,包括在服务器上提交了的事务但是日记文件已经不再服务器上的GTID集合,通常用于主从同步的从库初始状态更新。
主从中gtid的工作流程
简而言之,GTID的工作流程为:
-
master更新数据时,会在事务前产生GTID,一同记录到binlog日志中(SET @@SESSION.GTID_NEXT=)。
-
slave端的i/o 线程将变更的binlog,写入到本地的relay log中。
-
sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。
-
如果有记录,说明该GTID的事务已经执行,slave会忽略。
-
如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
gtid的生命周期
-
事务在原服务器执行提交后,会分配一个GTID,该GTID由uuid和尚未使用过的最小非零事务系列号组成。
-
每当二进制日志轮换或服务器关闭时,服务器都会将写入先前二进制日志文件的所有事务的 GTID 写入 mysql.gtid_executed表中。
-
如果为事务分配了 GTID,则通过将 GTID 添加到gtid_executed系统变量@@GLOBAL.gtid_executed( 此 GTID 集包含所有已提交 GTID 事务集的表示, gtid_executed系统变量中的 GTID 集是应用事务的完整记录,但 mysql.gtid_executed表不是。
-
在二进制日志数据传输到副本并存储在副本的中继日志中,副本读取 GTID 并设置其 gtid_next系统的值变量作为此 GTID。这告诉副本必须使用此 GTID 记录下一个事务。重要的是要注意副本集gtid_next在会话上下文中。
-
系统gtid_owned 变量 (@@GLOBAL.gtid_owned) 的副本显示当前正在使用的每个 GTID 以及拥有它的线程的 ID。如果 GTID 已被使用,则不会引发错误,并使用自动跳过功能忽略事务。
-
如果尚未使用 GTID,则副本应用复制的事务。因为 gtid_next设置为源已经分配的 GTID,所以副本不会尝试为此事务生成新的 GTID,而是使用存储在gtid_next的值.
-
如果在副本上启用了二进制日志记录,则 GTID 在提交时通过在事务开始时将其写入二进制日志。
-
如果在副本上禁用了二进制日志记录,则 GTID 通过将其直接写入 mysql.gtid_executed表中以原子方式持久化。MySQL 将一条语句附加到事务以将 GTID 插入表中。在这种情况下,该 mysql.gtid_executed表是副本上应用的事务的完整记录。
注意:在 MySQL 5.7 中,将 GTID 插入表中的操作对于 DML 语句是原子的,但对于 DDL 语句不是,因此如果服务器在涉及 DDL 语句的事务后意外退出,则 GTID 状态可能会变得不一致。从 MySQL 8.0 开始,DDL 语句和 DML 语句的操作都是原子的。
- gtid_executed在副本上提交复制事务后不久,通过将 GTID 添加到副本的系统变量 ( @@GLOBAL.gtid_executed) 中 的 GTID 集合中,GTID 被非原子地外部化 。至于源,这个 GTID 集包含所有已提交 GTID 事务集的表示。如果在副本上禁用二进制日志记录,则该 mysql.gtid_executed表也是副本上应用的事务的完整记录。如果在副本上启用了二进制日志记录,这意味着某些 GTID 仅记录在二进制日志中,则gtid_executed系统变量中的 GTID 集是唯一完整的记录。
mysql.gtid_executed表和global.gtid_executed变量
-
在master实例上,gtid_executed系统变量中的 GTID 集是应用事务的完整记录,但 mysql.gtid_executed表不是。
-
在slave实例上
-
- 禁用了binlog,则两者都是应用事务的完整记录
- 开启binlog,只有gtid_executed变量才是事务完整的记录
-
reset master 会重置gtid_executed表和变量,以及清空日志