mysql.gtid_executed 表的初始化和更新机制

目录

mysql.gtid_executed表是MySQL 5.7引入的关键GTID持久化存储机制,用于记录服务器已执行的所有GTID事务,其初始化和更新过程结合了内存变量与磁盘存储,确保GTID状态在重启后能准确恢复。

一、mysql.gtid_executed表的初始化过程

当MySQL实例启动时,gtid_executed变量的初始化是一个两阶段过程,结合了持久化存储和二进制日志扫描:

  1. 从mysql.gtid_executed表加载基础值

    • 实例启动时,首先从mysql.gtid_executed系统表中读取所有记录
    • 将这些记录的GTID集合合并,作为初始化@@GLOBAL.gtid_executed的基础值
    • 这是最快、最主要的数据来源,因为表中已持久化了大部分GTID信息
  2. 扫描Binlog文件进行验证和补充

    • 扫描磁盘上所有现存的(未被PURGE的)binlog文件
    • 解析每个binlog文件头部的Previous_gtids_log_event和文件体内的Gtid_log_event
    • 计算出该文件所包含的完整GTID区间,得到binlog_gtid_set集合
  3. 计算最终的gtid_executed

    • 最终值 = 从mysql.gtid_executed表加载的集合 ∪ binlog_gtid_set
    • 这样设计既保证效率 (从表加载速度快),又确保正确性(避免遗漏最新提交的事务)
  4. 计算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:服务正常关闭与重启

  1. 写入数据

    sql 复制代码
    INSERT INTO test_table VALUES (1, 'data');
    INSERT INTO test_table VALUES (2, 'data');
    INSERT INTO test_table VALUES (3, 'data');
  2. 关闭服务

    • 服务正常关闭时,当前binlog中的GTID(1-3)会被写入mysql.gtid_executed表
  3. 删除binlog后重启

    • 重启后,即使binlog被删除,mysql.gtid_executed表中仍有GTID:1-3
    • 这表明服务关闭时GTID已持久化到表中,而非依赖binlog

示例2:binlog rotate过程

  1. 当前状态
    • mysql.gtid_executed表:GTID:1-25
    • 当前binlog文件(mysql-bin.000001):包含GTID 26-27
  2. 执行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压缩过程

  1. 更新前表内容

    复制代码
    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
    ...
  2. 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参数控制

四、关键要点总结

  1. 持久化价值:mysql.gtid_executed表解决了MySQL 5.6中gtid_executed仅存在于内存的问题,避免了binlog丢失导致的GTID状态丢失
  2. 更新策略差异:主库和从库的更新策略不同,取决于binlog和log_slave_updates的配置
  3. 压缩机制:定期压缩GTID区间,避免表记录过多,提高查询效率
  4. 初始化保障:即使binlog丢失,也能通过表中持久化的GTID快速恢复状态
  5. 与gtid_purged关系:gtid_purged是gtid_executed的子集,表示已丢失的GTID(被purge的binlog中的事务)

通过这种设计,MySQL 5.7+在GTID持久化方面实现了数据一致性恢复效率的平衡,为高可用架构提供了可靠的基础。

相关推荐
alphaTao2 小时前
LeetCode 每日一题 2025/12/1-2025/12/7
数据库·算法·leetcode
马克学长2 小时前
SSM特种设备全生命周期管理系统8b729(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·特种设备管理·全生命周期
小馒头学python2 小时前
openEuler 向量数据库:Milvus 相似度搜索性能测试
数据库·milvus·openeuler
正在走向自律3 小时前
Oracle迁移实战:从兼容性挑战到平滑过渡金仓数据库的解决方案
数据库·oracle·国产数据库·金仓数据库·兼容性挑战·迁移成本
QAQalone3 小时前
MySQL实际项目中常用的 DDL 模板
数据库·mysql
Evand J3 小时前
【MATLAB例程】二维指纹对目标的一段轨迹定位,锚点数量可调。输出位置真值、估计值对比,附代码下载链接
开发语言·数据库·matlab
赵渝强老师3 小时前
【赵渝强老师】国产金仓数据库的体系架构
数据库·oracle·架构
此生只爱蛋3 小时前
【Redis】浅谈数据结构和内部编码和单线程架构
数据结构·数据库·redis
工藤学编程3 小时前
零基础学AI大模型之新版LangChain向量数据库VectorStore设计全解析
数据库·人工智能·langchain