目录
-
- 一、mysql.gtid_executed表的初始化过程
- 二、mysql.gtid_executed表的更新机制
-
- [1. 主库更新机制](#1. 主库更新机制)
- [2. 从库更新机制](#2. 从库更新机制)
- [3. 特殊场景更新](#3. 特殊场景更新)
- 三、实际示例说明
-
- 示例1:服务正常关闭与重启
- [示例2:binlog rotate过程](#示例2:binlog rotate过程)
- 示例3:GTID压缩过程
- 四、关键要点总结
mysql.gtid_executed表是MySQL 5.7引入的关键GTID持久化存储机制,用于记录服务器已执行的所有GTID事务,其初始化和更新过程结合了内存变量与磁盘存储,确保GTID状态在重启后能准确恢复。
一、mysql.gtid_executed表的初始化过程
当MySQL实例启动时,gtid_executed变量的初始化是一个两阶段过程,结合了持久化存储和二进制日志扫描:
-
从mysql.gtid_executed表加载基础值
- 实例启动时,首先从mysql.gtid_executed系统表中读取所有记录
- 将这些记录的GTID集合合并,作为初始化@@GLOBAL.gtid_executed的基础值
- 这是最快、最主要的数据来源,因为表中已持久化了大部分GTID信息
-
扫描Binlog文件进行验证和补充
- 扫描磁盘上所有现存的(未被PURGE的)binlog文件
- 解析每个binlog文件头部的Previous_gtids_log_event和文件体内的Gtid_log_event
- 计算出该文件所包含的完整GTID区间,得到binlog_gtid_set集合
-
计算最终的gtid_executed
- 最终值 = 从mysql.gtid_executed表加载的集合 ∪ binlog_gtid_set
- 这样设计既保证效率 (从表加载速度快),又确保正确性(避免遗漏最新提交的事务)
-
计算gtid_purged
- gtid_purged = gtid_executed - binlog_gtid_set
- 这个结果代表已从磁盘上被清除的binlog文件中所记录的事务
注意:binlog_gtid_simple_recovery参数(MySQL 5.7.7及之后版本默认为True)控制初始化过程:
- 当为True时,只需读取最新binlog文件即可
- 当为False时,需要遍历所有binlog文件,可能导致重启时间较长
二、mysql.gtid_executed表的更新机制
1. 主库更新机制
- BINLOG关闭:不生成GTID,mysql.gtid_executed表不更新
- BINLOG开启 :
- 非实时更新:在BINLOG发生切换(rotate)或服务关闭时才更新
- 更新内容:保存上一个BINLOG文件执行过的全部GTID
- 例如:当binlog文件从mysql-bin.000001切换到mysql-bin.000002时,才会将000001文件中的GTID写入表中
2. 从库更新机制
- BINLOG关闭或log_slave_updates关闭 :
- 实时更新:在执行事务时立即更新mysql.gtid_executed表
- 与用户事务一起提交,确保数据一致性
- BINLOG开启且log_slave_updates开启 :
- 与主库相同,在BINLOG切换或服务关闭时更新
3. 特殊场景更新
- RESET MASTER命令:清空mysql.gtid_executed表
- SET GLOBAL gtid_purged:设置mysql.gtid_executed表
- binlog rotate :触发表更新,同时会压缩GTID区间(如将1-25,26-27合并为1-27)
- 服务关闭:将当前二进制日志文件中的GTID集合写入表中
三、实际示例说明
示例1:服务正常关闭与重启
-
写入数据 :
sqlINSERT INTO test_table VALUES (1, 'data'); INSERT INTO test_table VALUES (2, 'data'); INSERT INTO test_table VALUES (3, 'data'); -
关闭服务 :
- 服务正常关闭时,当前binlog中的GTID(1-3)会被写入mysql.gtid_executed表
-
删除binlog后重启 :
- 重启后,即使binlog被删除,mysql.gtid_executed表中仍有GTID:1-3
- 这表明服务关闭时GTID已持久化到表中,而非依赖binlog
示例2:binlog rotate过程
- 当前状态 :
- mysql.gtid_executed表:GTID:1-25
- 当前binlog文件(mysql-bin.000001):包含GTID 26-27
- 执行flush binary logs :
- 触发binlog rotate,创建新文件mysql-bin.000002
- 将GTID 26-27写入mysql.gtid_executed表
- mysql.gtid_executed表更新为:GTID:1-27
- 新binlog文件(mysql-bin.000002)的Previous-GTIDs设为26-27
示例3:GTID压缩过程
-
更新前表内容 :
source_uuid: 05e16691-bf69-11e5-97cf-fa163e30f9a2 interval_start: 1, interval_end: 4334294 interval_start: 4334296, interval_end: 4352984 interval_start: 4352985, interval_end: 4352985 ... -
binlog rotate后 :
-
触发表压缩,合并连续区间
-
更新后表内容:
source_uuid: 05e16691-bf69-11e5-97cf-fa163e30f9a2
interval_start: 1, interval_end: 4334294
interval_start: 4334296, interval_end: 4352988 -
注意:压缩由后台线程
thread/sql/compress_gtid_table完成,受gtid_executed_compression_period参数控制
-
四、关键要点总结
- 持久化价值:mysql.gtid_executed表解决了MySQL 5.6中gtid_executed仅存在于内存的问题,避免了binlog丢失导致的GTID状态丢失
- 更新策略差异:主库和从库的更新策略不同,取决于binlog和log_slave_updates的配置
- 压缩机制:定期压缩GTID区间,避免表记录过多,提高查询效率
- 初始化保障:即使binlog丢失,也能通过表中持久化的GTID快速恢复状态
- 与gtid_purged关系:gtid_purged是gtid_executed的子集,表示已丢失的GTID(被purge的binlog中的事务)
通过这种设计,MySQL 5.7+在GTID持久化方面实现了数据一致性 与恢复效率的平衡,为高可用架构提供了可靠的基础。