mysql.gtid executed_MYSQL 5.7中新增的表GTID_EXECUTED

MYSQL 5.7中新增的表GTID_EXECUTED

88ee132e03a63143804a43b341cb2ad2.png

正文

MySQL 5.6版本开启GTID模式,必须要先打开参数log_slave_updates,简单来说就是一定在从机上再记录一份二进制日志。这样的无论对性能还是存储的开销,无疑会相应的增大。而MySQL 5.7版本开始无需在GTID模式下启用参数log_slave_updates,其中最重要的原因在于5.7在mysql库下引入了新的表gtid_executed,其表结构如下所示:

mysql> SHOW CREATE TABLE mysql.gtid_executed\G

*************************** 1. row ***************************

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=utf8mb4 STATS_PERSISTENT=0

1 row in set (0.00 sec)

简单来说,该表会记录当前执行的GTID。列source对应UUID,列interval_start/interval_end表示的是事务号。在MySQL 5.6中必须配置参数log_slave_updates的最重要原因在于当slave重启后,无法得知当前slave已经运行到的GTID位置,因为变量gtid_executed是一个内存值:

mysql> select @@global.gtid_executed\G

*************************** 1. row ***************************

@@global.gtid_executed: 7af7d3ea-933b-11e5-9da7-fa163e30f9a2:1-72054

1 row in set (0.00 sec)

所以MySQL 5.6的处理方法就是启动时扫描最后一个二进制日志,获取当前执行到的GTID位置信息。当然,如果DBA不小心将二进制日志删除了,那么这又会带来灾难性的问题。

因此,MySQL 5.7将gtid_executed这个值给持久化了。采用的技巧与MySQL 5.6处理SQL thread保存位置的方式一样,即将GTID值持久化保存在一张InnoDB表中,并与用户事务一起进行提交,从而实现数据的一致性:

START TRANSACTION;

# user statement

......

INSERT INTO mysql.gtid_executed VALUES (...)

END;

需要注意的是表mysql.gtid_executed是在主服务器和从服务器上有进行更新的,而表slave_relay_log_info仅在从服务器上更新。

MySQL 5.7对于表mysql.gtid_executed的更新策略也有些不同,如果没有主服务器没有开启log_bin或者从服务器没有开启log_slave_updates,其会每一个事物更新表gtid_executed,这样服务器重启后可以快速知道当前服务器执行到的GTID位置。因此,用户可能在服务器上看到类似如下的内容:

mysql> select * from mysql.gtid_executed;

+--------------------------------------+----------------+--------------+

| source_uuid | interval_start | interval_end |

+--------------------------------------+----------------+--------------+

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 1 | 4334294 |

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 4334296 | 4352984 |

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 4352985 | 4352985 |

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 4352986 | 4352986 |

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 4352987 | 4352987 |

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 4352988 | 4352988 |

......

那这样岂不是表gtid_executed中的记录会疯狂增长。为此,MySQL 5.7又引入了新的线程,用来对此表进行压缩,该线程如下所示:

mysql> select thread_id,thread_os_id,name,

-> processlist_command,processlist_state from threads

-> where name like '%compress%'\G

*************************** 1. row ***************************

thread_id: 39

thread_os_id: 23816

name: thread/sql/compress_gtid_table

processlist_command: Daemon

processlist_state: Suspending

1 row in set (0.01 sec)

参数gtid_executed_compression_period用来控制每执行多少个事务,对此表进行压缩,默认值为1000。因此,过一段时间后,上述的表mysql.gtid_executed会压缩成如下的内容:

mysql> select * from mysql.gtid_executed;

+--------------------------------------+----------------+--------------+

| source_uuid | interval_start | interval_end |

+--------------------------------------+----------------+--------------+

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 1 | 4334294 |

| 05e16691-bf69-11e5-97cf-fa163e30f9a2 | 4334296 | 4354329 |

......

如果MySQL服务器启用了二进制日志,则表mysql.gtid_executed的更新仅在二进制rotation时发生,因为发生重启等情况依旧可以通过扫描二进制日志判断得知当前运行的GTID位置。

开启log_slave_updates后,主从服务器性能有多少的差异,这是一个比较有意思的问题。不过IMG社区群中的西毒同学,已经发现了另一个有意思的问题,即主服务器将innodb_flush_log_at_trx_commit设置为0,依然能保证crash safe。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值