Mysql 5.7 Gtid内部学习(四) mysql.gtid_executed表Previous gtid Event的改变

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

之所以把mysql.gtid_executed表的作用和Previous gtid Event的改变放到一起进行描述是因为它们后面文章探讨的基础。这部分使用到了我自己使用C语言写的原生binlog解析工具infobin。
百度云盘下载如下:
http://pan.baidu.com/s/1jHIWUN0

一、Gtid event

为什么要先描述什么是Gtid event呢?因为后面会用到,实际上在中其核心元素就是一个形如:

31704d8a-da74-11e7-b6bf-52540a7d243:100009

的一个Gtid处于整个事务event中的开始,用于描述这个事务的Gtid是多少,当然在5.7中为了支持MTS其中还封装了last_commit/sequence_number。那么使用infobin工具查看一个insert单条语句完整事务的event包括如下:

>Gtid Event:Pos:234(0Xea) N_pos:299(0X12b) Time:1513135186 Event_size:65(bytes) 
Gtid:31704d8a-da74-11e7-b6bf-52540a7d243:100009 last_committed=0  sequence_number=1
-->Query Event:Pos:299(0X12b) N_Pos:371(0X173) Time:1513135186 Event_size:72(bytes) 
Exe_time:0  Use_db:test Statment(35b-trun):BEGIN /*!Trx begin!*/ Gno:100009
---->Map Event:Pos371(0X173) N_pos:415(0X19f) Time:1513135186 Event_size:44(bytes) 
TABLE_ID:108 DB_NAME:test TABLE_NAME:a Gno:100009
------>Insert Event:Pos:415(0X19f) N_pos:455(0X1c7) Time:1513135186 Event_size:40(bytes) 
Dml on table: test.a  table_id:108 Gno:100009 
>Xid Event:Pos:455(0X1c7) N_Pos:486(0X1e6) Time:1513135186 Event_size:31(bytes) 
COMMIT; /*!Trx end*/ Gno:100009

当然也可以使用mysqlbinlog进行分析,只是格式稍微不那么友好。

二、gtid_executed表的作用

这一部分是重点中的重点,也是我以前一直疑惑的,请大家细细品读。
官方文档这样描述gtid_executed表

Beginning with MySQL 5.7.5, GTIDs are stored in a table named gtid_executed, in the mysql
database. A row in this table contains, for each GTID or set of GTIDs that it represents, the UUID of the
originating server, and the starting and ending transaction IDs of the set; for a row referencing only a
single GTID, these last two values are the same.

也就是说gtid_executed表是Gtid持久化的一个工具,如前文所描述Gtid_state中的get_executed_gtids/get_lost_gtids/get_gtids_only_in_table/get_previous_gtids_logged这些数据都是存储在内存中的,那么在数据库重启后需要进行初始化,那么这需要读取Gtid持久化的介质,我们可以发现gtid_executed是一个innodb表建表语句如下,并且我们可以手动更改它,但是千万不要这么干:

       Table: gtid_executed
Create Table: 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=utf8 STATS_PERSISTENT=0

那么在5.7.5以前没有gtid_executed表不是也没有问题吗?其实除了gtid_executed表以外我们还有一个Gtid持久化的介质那就是binlog中的Gtid event。所以总结一下Gtid持久化介质:

  • gtid_executed表
  • binlog中的gtid event

那么既然有了binlog的gtid event进行持久化那么为什么还需要gtid_executed表呢?这实际上就是5.7.5过后的一个优化,我们可以反过来思考在5.6中如果使用了Gtid做从库,从库如果不开启binlog并且同时设置log_slave_updates=ture那么从库的执行过的Gtid事务是没有办法持久化的。我们来一段5.6官方文档对于搭建Gtid从库的其中一步:

Step 3: Restart both servers with GTIDs enabled. To enable binary logging with global
transaction identifiers, each server must be started with GTID mode, binary logging, slave update
logging enabled, and with statements that are unsafe for GTID-based replication disabled. In addition,
you should prevent unwanted or accidental updates from being performed on either server by starting
both in read-only mode. This means that both servers must be started with (at least) the options shown
in the following invocation of mysqld_safe:
shell> mysqld_safe --gtid_mode=ON --log-bin --log-slave-updates --enforce-gtid-consistency &

开启binlog同时设置设置log_slave_updates=ture必然造成一个问题,实际上从库很多时候我们是不需要做级联slave,设置log_slave_updates=ture会造成需要额外的空间和性能开销。自然这种情况下我们需要另外的一种Gtid持久化介质,而并不是binlog中的Gtid event。为了解决这个问题,5.7中gtid_executed表应运而生了。然而gtid_executed表是否需要实时更新呢?显然在slave端不开启binlog或者开启binlog不设置log_slave_updates=ture的情况下它需要实时更新,因为I/O thread执行过得Gtid是必须持久化的,而在主库上因为有binlog的Gtid event的存在他是不需要实时更新的,这样不同的对待方式也能够减轻负担提高性能。
同时在官方文档上也有相关描述它分为是否开始binlog进行描述,但是其描述并不是最详细的。所以这部分在后面我会进行详细描述。

三、Previous gtid Event的改变

Previous gtid Event是包含在每一个binlog的开头用于描述所有以前binlog所包含的全部Gtid的一个集合(包括已经删除的binlog)如:

da267088-9c22-11e7-ab56-5254008768e3:1-32

在5.6中如果不开启Gtid,那么binlog是不会包含这个Previous gtid Event的,但是在5.7中不开启Gtid也会包含这个Previous gtid Event,实际这一点的改变其意义也是非常巨大,简单的说他为快速扫描binlog(binlog_gtid_simple_recovery=ture)获得正确Gtid集合提供了基础,否则将会扫描大量的binlog,从而浪费I/O性能,这是5.6中一个非常严重的问题,在5.7的官方文档这样描述:

When binlog_gtid_simple_recovery=TRUE, which is the default in MySQL 5.7.7 and
later, the server iterates only the oldest and the newest binary log files and the values of
gtid_purged and gtid_executed are computed based only on Previous_gtids_log_event
or Gtid_log_event found in these files. This ensures only two binary log files are iterated during
server restart or when binary logs are being purged

当然这部分也会在后面进行详细的描述,这里只是简单提一下。那么我们通过mysqlbinlog 和infobin工具分别确认这一点。

  • 5.6. 26 不开启Gtid

mysqlbinlog:

*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#171211 16:20:10 server id 20155  end_log_pos 120 CRC32 0x12617db7      Start: binlog v 4, server v 5.6.26-74.0-log created 171211 16:20:10
# Warning: this binlog is either in use or was not closed properly.
# at 120
#171211 16:20:14 server id 20155  end_log_pos 192 CRC32 0x696752cb      Query   thread_id=30    

infobin:

------------Detail now--------------
>Format description log Event:Pos:4(0X4) N_pos:120(0X78) Time:1512980410 Event_size:116(bytes) 
-->Query Event:Pos:120(0X78) N_Pos:192(0Xc0) Time:1512980414 Event_size:72(bytes) 
Exe_time:0  Use_db:test Statment(35b-trun):BEGIN /*!Trx begin!*/ Gno:0
---->Map Event:Pos192(0Xc0) N_pos:241(0Xf1) Time:1512980414 Event_size:49(bytes) 
TABLE_ID:91 DB_NAME:test TABLE_NAME:testpo Gno:0
------>Insert Event:Pos:241(0Xf1) N_pos:281(0X119) Time:1512980414 Event_size:40(bytes) 
Dml on table: test.testpo  table_id:91 Gno:0 
>Xid Event:Pos:281(0X119) N_Pos:312(0X138) Time:1512980414 Event_size:31(bytes) 
COMMIT; /*!Trx end*/ Gno:0

我们并没有发现Previous gtid Event,也就是5.6如果不开启Gtid则不包含Previous gtid Event。

  • 5.7.14

mysqlbinlog:

/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#171211 16:26:49 server id 1  end_log_pos 123 CRC32 0xf9a36298  Start: binlog v 4, server v 5.7.14-7-debug-log created 171211 16:26:49
# Warning: this binlog is either in use or was not closed properly.
# at 123
#171211 16:26:49 server id 1  end_log_pos 194 CRC32 0x5865633f  **Previous-GTIDs**
# da267088-9c22-11e7-ab56-5254008768e3:1-32
# at 194

infobin:

------------Detail now--------------
>Format description log Event:Pos:4(0X4) N_pos:123(0X7b) Time:1512980809 Event_size:119(bytes) 
>Previous gtid Event:Pos:123(0X7b) N_pos:194(0Xc2) Time:1512980809 Event_size:71(bytes) 
>Anonymous gtid Event:Pos:194(0Xc2) N_pos:259(0X103) Time:1512980814 Event_size:65(bytes) 
Gtid:Anonymous(Gno=0) last_committed=0  sequence_number=1
-->Query Event:Pos:259(0X103) N_Pos:331(0X14b) Time:1512980814 Event_size:72(bytes) 
Exe_time:0  Use_db:test Statment(35b-trun):BEGIN /*!Trx begin!*/ Gno:0
---->Map Event:Pos331(0X14b) N_pos:380(0X17c) Time:1512980814 Event_size:49(bytes) 
TABLE_ID:154 DB_NAME:test TABLE_NAME:testpo Gno:0
------>Insert Event:Pos:380(0X17c) N_pos:420(0X1a4) Time:1512980814 Event_size:40(bytes) 
Dml on table: test.testpo  table_id:154 Gno:0 
>Xid Event:Pos:420(0X1a4) N_Pos:451(0X1c3) Time:1512980814 Event_size:31(bytes) 
COMMIT; /*!Trx end*/ Gno:0

我们清晰的看到这里包含了Previous gtid Event,当然我们还发现了Anonymous gtid Event这也是5.7中变化,5.7中即使不开始Gtid每个事务也包含也一个Anonymous gtid Event,虽然没有Gtid但是它任然包含了 last_committed/sequence_number。

四、本节小结

学习完本节至少能够学习到:

  • 1、什么是Gtid event。包含什么重要元素。
  • 2、为什么需要gtid_executed表及其作用。
  • 3、5.7中Previous gtid Event发生了哪些改变。
  • 4、简单了解Previous gtid Event的改变意味着什么。

作者微信:


微信.jpg
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
分布式计算 关系型数据库 MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
49 3
|
1月前
|
关系型数据库 MySQL Java
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
这篇文章是关于如何使用Django框架配置MySQL数据库,创建模型实例,并自动或手动创建数据库表,以及对这些表进行操作的详细教程。
61 0
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
|
1月前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
71 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
1月前
|
Java 关系型数据库 MySQL
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
这篇文章是关于如何使用Spring Boot框架通过JdbcTemplate操作MySQL数据库的教程。
25 0
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
|
1月前
|
关系型数据库 MySQL 数据库
mysql关系型数据库的学习
mysql关系型数据库的学习
18 0
|
8天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
23 1
|
10天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
25 4
|
1月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
61 3
Mysql(4)—数据库索引
|
17天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
85 1
|
19天前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
61 2