Skip to content

gtid_executed

xiaoboluo768 edited this page Jul 3, 2020 · 5 revisions
  • 该表提供查询与当前实例中的数据一致的GTID集合(该表用于存储所有事务分配的 GTID集合,GTID集合由UUID集合构成,每个UUID集合的组成为:uuid:interval[:interval]...,例如 :28b13b49-3dfb-11e8-a76d-5254002a54f2:1-600401,3ff62ef2-3dfb-11e8-a448-525400c33752:1-110133)
  • GTID是在整个复制拓扑中是全局唯一的,GTID中的事务号是一个单调递增的无间隙数字。正常情况下,客户端的数据修改在执行commit时会分配一个GTID,且会记录到binlog中,这些GTID通过复制组件在其他实例中进行重放时也会保留GTID来源不变。但是如果客户端自行使用sql_log_bin变量关闭了binlog记录或者客户端执行的是一个只读事务,那么server不会分配GTID,在binlog中也不会有GTID记录
  • 当某个从库接受到自己的GTID集合中已经包含的GTID时,会忽略这个已存在的GTID,并且不会报错,事务也不会被执行
  • 从MySQL 5.7.5开始,GTID存储在mysql数据库的名为gtid_executed的表中。对于每个GTID集合,默认情况下值记录每个GTID集合的起始和结束的事务号对应的GTID,该表只在数据库初始化或者执行update_grade升级的时候创建,不允许手工创建与修改。当实例本身有客户端访问数据写入或者有从其他主库通过复制插件同步数据的时候,该表中会有新的GTID记录写入,另外,该表中的记录还会在binlog滚动或者实例重启的时候被更新(日志滚动时该表需要把除了最新的binlog之外其他binlog中的所有GTID集合记录到该表中,实例重启时,需要把所有的binlog中的GTID集合记录到该表中)
  • 由于有mysql.gtid_executed表记录GTID(避免了binlog丢失的时候丢失GTID历史记录),所以,从5.7.5版本开始,在复制拓扑中的从库允许关闭binlog,也允许在binlog开启的情况下关闭log_slave_updates变量
  • 由于GTID必须要再gtid_mode为ON或者为ON_PERMISSIVE时才会生成,所以自然该表中的记录也需要依赖于gtid_mode变量为ON或ON_PERMISSIVE时才会进行记录,另外,该表中是否实时存储GTID,取决于binlog日志是否开启,或者binlog启用时是否启用log_slave_updates变量,如下:
  • 当禁用二进制日志记录(log_bin为OFF),或者启用binlog但禁用log_slave_updates,则Server会在每个事物提交时把属于该事物的GTID同时更新到该表中。此时,该表的GTID周期性自动压缩功能激活,每达到gtid_executed_compression_period系统变量指定的事物数量压缩一次该表中的GTID集合(也就是把每个UUID对应的事务号的记录取一个最大值,取一个最小值,删除中间值),要注意:周期性自动压缩功能仅针对从库,对主库无效,因为主库必须启用binlog,且log_slave_updates参数不影响主库
  • 如果启用二进制日志记录(log_bin为ON)且log_slave_updates参数也启用,则周期性自动压缩功能失效,该表中的记录只会在binlog日志滚动或者服务器关闭时才会进行压缩,且会把除了最后一个binlog之外,其他所有binlog中包含的GTID集合写入该表中
  • 注意:
* 如果启用二进制日志记录(log_bin为ON)且log_slave_updates参数也启用,那么该表不会实时记录GTID,也就是说,完整的GTID集合,有一部分记录在该表中,有一部分是记录在binlog中的,如果一旦server发生crash,那么在crash recovery时会读取binlog中最新的GTID集合并合并到该表中 * 该表中的记录在执行reset master语句时会被清空
  • 表结构定义
CREATE TABLE `gtid_executed` (
  `source_uuid` char(36) COLLATE utf8_bin 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 COLLATE=utf8_bin STATS_PERSISTENT=0;
  • 该表中的记录周期性执行压缩示例
# 假设表中有如下实时记录的GTID记录
mysql> SELECT * FROM mysql.gtid_executed;
+ -------------------------------------- + ---------- ------ + -------------- +
| source_uuid | interval_start | interval_end |
| -------------------------------------- + ---------- ------ + -------------- |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37 | 37 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 38 | 38 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 39 | 39 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 40 | 40 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 41 | 41 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 42 | 42 |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 43 | 43 |
...

# 那么,每达到gtid_executed_compression_period变量定义的事务个数时,激活压缩功能,GTID被压缩为一行记录,如下
+ -------------------------------------- + ---------- ------ + -------------- +
| source_uuid | interval_start | interval_end |
| -------------------------------------- + ---------- ------ + -------------- |
| 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37 | 43 |
...

# 注意:当gtid_executed_compression_period系统变量设置为0时,周期性自动压缩功能失效,你需要预防该表被撑爆的风险
  • 表字段含义
  • source_uuid:代表数据来源的GTID集合
  • interval_start:每个UUID集合的最小事务号
  • interval_end:每个UUID集合的最大事务号
  • 表记录内容示例
root@localhost : mysql 01:05:09> select * from gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| ec123678-5e26-11e7-9d38-000c295e08a0 |              1 |       182218 |
| ec123678-5e26-11e7-9d38-000c295e08a0 |         182219 |       182288 |
+--------------------------------------+----------------+--------------+
2 rows in set (0.00 sec)
  • 对该表的压缩功能由名为 thread/sql/compress_gtid_table 的专用前台线程执行。该线程使用SHOW PROCESSLIST无法查看,但它可以在performance_schema.threads表中查看到(线程 thread/sql/compress_gtid_table 大多数时候都处于休眠状态,直到每满gtid_executed_compression_period个事务之后,该线程被唤醒以执行前面所述的对mysql.gtid_executed表的压缩。然后继续进入睡眠状态,直到下一次满gtid_executed_compression_period个事务,然后被唤醒再次执行压缩,以此类推,无限重复此循环。但如果当关闭binlog或者启用binlog但关闭log_slave_updates变量时,gtid_executed_compression_period变量被设置为了0,那么意味着该线程会始终处于休眠状态且永不会唤醒),如下所示:
mysql> SELECT * FROM performance_schema.threads WHERE NAME LIKE '%gtid%'\G
*************************** 1. row ***************************
          THREAD_ID: 26
               NAME: thread/sql/compress_gtid_table
               TYPE: FOREGROUND
     PROCESSLIST_ID: 1
   PROCESSLIST_USER: NULL
   PROCESSLIST_HOST: NULL
     PROCESSLIST_DB: NULL
PROCESSLIST_COMMAND: Daemon
   PROCESSLIST_TIME: 1509
  PROCESSLIST_STATE: Suspending
   PROCESSLIST_INFO: NULL
   PARENT_THREAD_ID: 1
               ROLE: NULL
       INSTRUMENTED: YES
            HISTORY: YES
    CONNECTION_TYPE: NULL
       THREAD_OS_ID: 18677

上一篇:func表 |下一篇:time_zone表

Clone this wiki locally