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持久化方面实现了数据一致性 与恢复效率的平衡,为高可用架构提供了可靠的基础。

相关推荐
邓工说电11 分钟前
智慧断路器安全吗?数据加密、离线保护与合规认证全解读
大数据·数据库·人工智能·智能断路器·炜晔科技
for_ever_love__20 分钟前
MySQL 全文索引实战:FULLTEXT、ngram 中文分词与 MATCH AGAINST 到底该怎么用
java·python·mysql·全文检索·分词·索引·ngram
adinnet202629 分钟前
企业微调大模型(Fine-tuning):先吃透 RAG 还是先训自己的模型
大数据·数据库
上位机妹子1 小时前
EF Core 两种继承映射:每层次一张表(TPH)与每类型一张表(TPT)
数据库·c#·.netcore·ef core
小马同学-1 小时前
Redis消息队列与客户端编程
数据库·redis
for_ever_love__2 小时前
MySQL 高频面试题 30 问:索引、事务、锁、日志、主从与分库分表(MySQL 8.0 版)
java·数据库·spring boot·mysql·spring cloud·面试·总结
染指11102 小时前
140.Agent-多Agent框架-Agent执行Skills流程
数据库·人工智能·设计模式·langchain·agents
fengkai45452 小时前
十二、Redis -2
运维·数据库·redis·容器