MySQL GTID详解

2023-12-15 11:35:52

概念

GTID 全局事务唯一标识(? global transaction identifier)

格式

单个GTID由两部分组成 ,用冒号分割;前面一部分为server_uuid,后面一部分transaction_id是由事务在源上提交的顺序确定的序列号

GTID = server_uuid:transaction_id

?举例:

03775d13-0fe8-11e9-b537-38bc01691bfc:1?

该GTID是在UUID 为775d13-0fe8-11e9-b537-38bc01691bfc 的服务器上提交的第一个事务

GTID集合?

GTID集合 可以包括一个或多个的GTID集合。

GTID 集在 MySQL 服务器中以多种方式使用,

1 系统变量 gitd_executed和 gtid_purged存储的就是GTID集合 ,后面会详细介绍这两个参数

mysql> select @@GLOBAL.gtid_executed;
+-------------------------------------------------+
| @@GLOBAL.gtid_executed                          |
+-------------------------------------------------+
| 03775d13-0fe8-11e9-b537-38bc01691bfc:1-55063960 |
+-------------------------------------------------+
1 row in set (0.00 sec)

mysql>
mysql>
mysql> select  @@GLOBAL.gtid_purged;
+-------------------------------------------------+
| @@GLOBAL.gtid_purged                            |
+-------------------------------------------------+
| 03775d13-0fe8-11e9-b537-38bc01691bfc:1-54852116 |
+-------------------------------------------------+
1 row in set (0.00 sec)

2 START SLAVE 中的子句 UNTIL SQL_BEFORE_GTIDS 和?UNTIL SQL_AFTER_GTIDS 可以用来使副本仅处理 GTID 集中的第一个 GTID 之前的事务,或在 GTID 集中的最后一个 GTID 之后停止

3 内建函数??GTID_SUBSET()?and?GTID_SUBTRACT()? 需要一个GTID集合作为参数传入

存储

GTID 存储在 mysql.gtid_executed中 名为 的表中。

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
mysql.gtid_execulated 表压缩

gtid_executed_compression_period?该变量的默认值为 1000,这意味着默认情况下,每 1000 个事务后就会执行一次表压缩。为 0 事会完全阻止执行压缩,会导致该表的磁盘空间量大幅增加。

经过压缩之后查看该表

mysql> select *  from gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| 03775d13-0fe8-11e9-b537-38bc01691bfc |              1 |     55033090 |
+--------------------------------------+----------------+--------------+
1 row in set (0.00 sec)

GTID 生命周期

GTID的生命周期由以下步骤组成:

  1. 事务在复制源服务器上执行并提交。该客户端事务被分配一个由源的 UUID 和该服务器上尚未使用的最小非零事务序列号组成的 GTID。GTID 被写入源的二进制日志(紧邻日志中事务本身之前)。如果客户端事务没有写入二进制日志(例如,因为事务被过滤掉,或者事务是只读的),则不会为其分配 GTID。

  2. 如果为事务分配了 GTID,则 GTID 会在提交时通过在事务开始时将其写入二进制日志(作为?Gtid_log_event)以原子方式持久保存。每当二进制日志轮换或服务器关闭时,服务器都会将前一个二进制日志文件的所有事务的 GTID 写入表中?mysql.gtid_executed

  3. 如果为事务分配了 GTID,则通过将 GTID 添加到系统变量gtid_executed ( @@GLOBAL.gtid_executed)?中的 GTID 集合,以非原子方式(事务提交后不久)将 GTID 外部化。该 GTID 集包含所有已提交 GTID 事务集的表示,并且在复制中用作表示服务器状态的令牌。启用二进制日志记录(根据源的要求)后,系统变量gtid_executed中的 GTID 集是所应用事务的完整记录,但表?mysql.gtid_executed不是,因为最新的历史记录仍在当前二进制日志文件中。

  4. 在二进制日志数据传输到副本并存储在副本的中继日志中之后,副本读取 GTID 并设置其系统变量gtid_next的值为此 GTID。这告诉副本必须使用此 GTID 记录下一个事务。需要注意的是,副本集位于gtid_next会话上下文中。

  5. 副本会验证是否还没有线程取得 GTID 的所有权gtid_next才能处理事务。通过在处理事务本身之前首先读取并检查复制事务的 GTID,副本不仅可以保证之前没有具有此 GTID 的事务应用于副本,而且还没有其他会话已经读取此 GTID 但尚未读取已提交关联交易。因此,如果多个客户端尝试同时应用同一事务,服务器会通过仅让其中一个客户端执行来解决此问题。副本的系统gtid_owned?变量 (?@@GLOBAL.gtid_owned) 显示当前正在使用的每个 GTID 以及拥有它的线程的 ID。如果GTID已经被使用,则不会引发错误,并且使用自动跳过功能来忽略该事务。

  6. 如果尚未使用 GTID,副本将应用复制的事务。由于?gtid_next被设置为源已分配的 GTID,因此副本不会尝试为此事务生成新的 GTID,而是使用 中存储的 GTID?gtid_next

  7. 如果在副本上启用了二进制日志记录,则 GTID 会在提交时通过在事务开始时将其写入二进制日志(作为?Gtid_log_event)以原子方式持久保存。每当二进制日志轮换或服务器关闭时,服务器都会将写入前一个二进制日志文件的所有事务的 GTID 写入表中?mysql.gtid_executed

  8. 如果在副本上禁用二进制日志记录,则通过将 GTID 直接写入?mysql.gtid_executed表中来以原子方式持久保存 GTID。MySQL 在事务中附加一条语句,将 GTID 插入表中。在这种情况下,该?mysql.gtid_executed表是应用于副本的事务的完整记录。请注意,在 MySQL 5.7 中,将 GTID 插入表的操作对于 DML 语句来说是原子的,但对于 DDL 语句来说不是,因此如果服务器在涉及 DDL 语句的事务后意外退出,GTID 状态可能会变得不一致。从 MySQL 8.0 开始,DDL 语句和 DML 语句的操作都是原子的。

  9. 在副本上提交复制事务后不久,GTID 将通过将其添加到 副本gtid_executed的系统变量 (?@@GLOBAL.gtid_executed) 中的 GTID 集合来非原子地外部化。至于源,该 GTID 集包含所有已提交的 GTID 事务集的表示。如果在副本上禁用二进制日志记录,则该?mysql.gtid_executed表也是副本上应用的事务的完整记录。如果在副本上启用了二进制日志记录,这意味着某些 GTID 仅记录在二进制日志中,则系统变量中的 GTID 集gtid_executed是唯一完整的记录。

参数解读
enforce_gtid_consistency?

Command-Line Format(命令行格式)--enforce-gtid-consistency[=value]
System Variable(系统变量)enforce_gtid_consistency
Scope(范围)Global
Dynamic(动态的)Yes
Type(类型)Enumeration
Default Value(默认值)OFF
Valid Values(有效值)

OFF

ON

WARN

根据此变量的值,服务器通过仅允许执行可以使用 GTID 安全记录的语句来强制执行 GTID 一致性。您?必须在启用基于 GTID 的复制之前设置此变量 为?ON

可以配置的值为 :

  • OFF:所有事务都允许违反GTID一致性。

  • ON:任何事务都不允许违反GTID一致性。

  • WARN:允许所有事务违反 GTID 一致性,但在这种情况下会生成警告。WARNMySQL 5.7.6 中添加。

?

当设置为 ON?时,?只能记录可以使用 GTID 安全语句记录的语句?,因此此处列出的操作不能与此选项一起使用:

仅当语句发生二进制日志记录时才生效。如果服务器上禁用了二进制日志记录,或者语句由于被过滤器删除而未写入二进制日志,则不会对未记录的语句检查或强制执行 GTID 一致性。

gtid_executed_compression_period

Command-Line Format--gtid-executed-compression-period=#
System Variablegtid_executed_compression_period
ScopeGlobal
DynamicYes
TypeInteger
Default Value1000
Minimum Value0
Maximum Value4294967295

每次处理这么多事务时?压缩表mysql.gtid_executed。当服务器上启用二进制日志记录时,不会使用此压缩方法,而是?mysql.gtid_executed在每次二进制日志轮转时对表进行压缩。当服务器上禁用二进制日志记录时,压缩线程将休眠,直到执行了指定数量的事务,然后唤醒以执行表的压缩?mysql.gtid_executed。将此系统变量的值设置为0意味着线程永远不会唤醒,因此不使用这种显式压缩方法。相反,压缩会根据需要隐式发生。

gtid_mode?

ommand-Line Format--gtid-mode=MODE
System Variablegtid_mode
ScopeGlobal
DynamicYes
TypeEnumeration
Default ValueOFF
Valid Values

OFF

OFF_PERMISSIVE

ON_PERMISSIVE

ON

?控制是否启用基于 GTID 的日志记录以及日志可以包含的事务类型。在 MySQL 5.7.6 之前,此变量--gtid-mode是只读的,并且仅在服务器启动时使用 。在 MySQL 5.7.5 之前,使用 ??--gtid-mode=ON?启动服务器要求服务器也使用?--log-bin和?--log-slave-updates选项启动。从 MySQL 5.7.5 开始,这不再是一个要求。

MySQL 5.7.6 允许动态设置此变量。您必须具有足够的权限才能设置全局系统变量。

enforce_gtid_consistency必须先设置ON为 才能设置?gtid_mode=ON

MySQL 5.7.6 及更高版本中记录的事务可以是匿名的,也可以使用 GTID。匿名事务依靠二进制日志文件和位置来识别特定事务。GTID 事务有一个唯一的标识符,用于引用事务。OFF_PERMISSIVEMySQL 5.7.6 中添加的和?模式ON_PERMISSIVE允许在拓扑中混合这些事务类型。现在不同的模式是:

  • OFF:新事务和复制事务都必须是匿名的。

  • OFF_PERMISSIVE:新事务是匿名的。复制事务可以是匿名事务,也可以是 GTID 事务。

  • ON_PERMISSIVE:新事务是GTID事务。复制事务可以是匿名事务,也可以是 GTID 事务。

  • ON:新事务和复制事务都必须是GTID事务。

从一个值到另一个值的更改一次只能是一步。例如,如果?gtid_mode当前设置为?OFF_PERMISSIVE,则可以更改为?OFFON_PERMISSIVE,但不能更改为ON

gtid_next

System Variablegtid_next
ScopeSession
DynamicYes
TypeEnumeration
Default ValueAUTOMATIC
Valid Values

AUTOMATIC

ANONYMOUS

<UUID>:<NUMBER>

该变量用于指定 是否以及如何获取下一个GTID。

设置此系统变量的会话值是一项受限制的操作。会话用户必须具有足够的权限才能设置受限会话变量。请参见?第 5.1.8.1 节“系统变量权限”

gtid_next可以采用以下任意值:

  • AUTOMATIC:使用下一个自动生成的全局事务ID。

  • ANONYMOUS:事务没有全局标识符,仅通过文件和位点来标识。

  • 全局事务ID:??UUID:NUMBER?。

上述哪个选项准确取决于gtid_mode?的设置,如果是gtid_mode = OFF,?则设置此变量无效。

将此变量设置为?UUID:NUMBER并提交或回滚事务后,SET GTID_NEXT必须在任何其他语句之前再次发出显式语句。

gtid_owned

System Variablegtid_owned
ScopeGlobal, Session
DynamicNo
TypeString
Unitset of GTIDs

?

该只读变量主要供内部使用。其内容取决于其范围。

gtid_executed

System Variablegtid_executed
ScopeGlobal
DynamicNo
TypeString
Unitset of GTIDs

?此变量包含在服务器上执行的所有事务的集合以及已由语句SET gtid_purged 设置的 GTID集合。

这与SHOW MASTER STATUS?和 SHOW SLAVE STATUS的输出中的Executed_Gtid_Set列?的值相同?。

该变量的值是 GTID 集,

在任何给定时间可以在二进制日志中找到的事务集等于?GTID_SUBTRACT(@@GLOBAL.gtid_executed, @@GLOBAL.gtid_purged);也就是说,二进制日志中尚未清除的所有事务。

发出RESET MASTER会导致该变量的全局值(但不是会话值)重置为空字符串。除了由于RESET MASTER 原因而清除该集合时,GTID 不会以其他方式从该集合中删除?。

在 MySQL 5.7.7 之前,此变量还可以与会话范围一起使用,其中它包含当前会话中写入缓存的事务集的表示。MySQL 5.7.7 中已弃用会话范围。

gtid_purged?

System Variablegtid_purged
ScopeGlobal
DynamicYes
TypeString
Unitset of GTIDs


系统变量( gtid_purged)?的全局值?@@GLOBAL.gtid_purged是一个 GTID 集合,由服务器上已提交但不存在于服务器上任何二进制日志文件中的所有事务的 GTID 组成。????????gtid_purged是 gtid_executed的子集?。GTID 的以下类别位于????????gtid_purged:

  • 在副本上禁用二进制日志记录的情况下提交的复制事务的 GTID。

  • 写入二进制日志文件(现已被清除)的事务的 GTID。

  • 由语句SET @@GLOBAL.gtid_purged?显式添加到集合中的 GTID .

发出 RESET MASTER 会导致gtid_purged 的值重置为空字符串。

可以手动设置?gtid_purged 的值,以便在服务器上记录某个 GTID 集中的事务已被应用,尽管它们不存在于服务器上的任何二进制日志中。此操作的一个示例用例是当您正在恢复服务器上一个或多个数据库的备份,但您没有包含服务器上事务的相关二进制日志时。

在 MySQL 5.7 中,仅当 gtid_executed?为空字符串时才可以更新 gtid_purged 的值 。因此gtid_purged为空字符串。当复制之前尚未开始,或者复制之前未使用 GTID 时,就会出现这种情况。

SET @@GLOBAL.gtid_purged = 'gtid_set'

文章来源:https://blog.csdn.net/weixin_48154829/article/details/134811880
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。