8.0 新特性-Generated Invisible Primary Key

文若2年前技术文章447

说明

MySQL Innodb 引擎采用的是 IOT(索引组织表)存储方式,主键的重要性就不言而喻。在早期版本用户如果没有显式指定主键,会自动生成隐藏主键 row_id 来组织 B+ 树,隐藏主键 row_id 只会作用于 MVCC、Redo 和 Undo 等内部机制,无法在复制模块中使用。一些大数据组件生成的表结构,往往都没有主键设计,会出现全表扫描回放问题,带来非常大的主备延迟。而且 MySQL 一些周边软件 gh-ost、DTS 服务等,都有依赖主键设计,没有主键会降低数据库的可维护性。

1. GIPK 介绍

Generated Invisible Primary Keys 简称 GIPK,是 2022 年 7 月 16 日 MySQL 发布 8.0.30 版本中的新特性,仅适用于 Innodb 引擎。

1.1 参数设置

GIPK 特性,通过 sql_generate_invisible_primary_key 参数来控制是否开启,默认是关闭状态。

下面的实验,在 GIPK 禁用的状态下,创建一张 auto_0 表,随后开启 GIPK 特性,然后创建 auto_1 表。

mysql> SELECT @@sql_generate_invisible_primary_key;
+--------------------------------------+
| @@sql_generate_invisible_primary_key |
+--------------------------------------+
|                                    0 |
+--------------------------------------+
1 row in set (0.00 sec)

mysql> CREATE TABLE auto_0 (c1 VARCHAR(50), c2 INT);
Query OK, 0 rows affected (0.02 sec)

mysql> SET sql_generate_invisible_primary_key=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@sql_generate_invisible_primary_key;
+--------------------------------------+
| @@sql_generate_invisible_primary_key |
+--------------------------------------+
|                                    1 |
+--------------------------------------+
1 row in set (0.00 sec)

mysql> CREATE TABLE auto_1 (c1 VARCHAR(50), c2 INT);
Query OK, 0 rows affected (0.04 sec)

实验 show create table 对比两张表结构是否有不同:

carbon.png

发现在开启 GIPK 情况下,未指定主键创建表,MySQL 会帮助我们创建名为 my_row_id 主键:

my_row_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT INVISIBLE PRIMARY KEY

2.2 可见性测试

向表 auto_1 表中插入数据:

insert into auto_1 values('a', 1),('b', 2),('c', 3),('d', 4),('e', 5);

执行查询,发现默认是不可见的:

select * from auto_1;
-- 结果:
+------+------+
| c1   | c2   |
+------+------+
| a    |    1 |
| b    |    2 |
| c    |    3 |
| d    |    4 |
| e    |    5 |
+------+------+

除非用户主动指定该字段:

select my_row_id, c1, c2 from auto_1;
-- 结果:
+-----------+------+------+
| my_row_id | c1   | c2   |
+-----------+------+------+
|         1 | a    |    1 |
|         2 | b    |    2 |
|         3 | c    |    3 |
|         4 | d    |    4 |
|         5 | e    |    5 |
+-----------+------+------+

查询元数据库,是可以查到相关信息:

select * from information_schema.COLUMNS where TABLE_NAME='auto_1' and COLUMN_KEY = 'PRI'\G

carbon.png

2.3 修改元数据可见性

开启 GIPK 后,默认会在 show create table 和 information_schema 等元数据库信息中看到,用户可以通过下方参数实现隐藏 my_row_id 的元数据信息,默认不隐藏:

select @@show_gipk_in_create_table_and_information_schema;

2.4 修改查询可见性

可通过 ALTER 语句将 my_row_id 不可见属性进行修改:

 ALTER TABLE `auto_1` ALTER column my_row_id set visible;

carbon.png

通过下方语句可修改为不可见:

ALTER TABLE `auto_1` ALTER column my_row_id set invisible;

2. GIPK 测试

2.1 Binlog 分析

看到 GIPK 特性,我的第一反应是 “能否解决无主键表带来的延迟问题?” 下面通过解析 Binlog 进行验证:

SET @@SESSION.GTID_NEXT= '4f4ab2eb-b0fd-11ed-b9e2-fa7581637800:15711'/*!*/;
# at 15439012
#230223 13:45:44 server id 553306  end_log_pos 15439315 CRC32 0x82a51a79 	Query	thread_id=201180	exec_time=0	error_code=0
SET TIMESTAMP=1677131144/*!*/;
SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=45/*!*/;
CREATE TABLE `auto_1` (
  `my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */,
  `c1` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `c2` int DEFAULT NULL,
  PRIMARY KEY (`my_row_id`)
)
-- 插入
### INSERT INTO `test`.`auto_1`
### SET
###   @1=1
###   @2='a'
###   @3=1
### INSERT INTO `test`.`auto_1`
### SET
###   @1=2
###   @2='b'
###   @3=2
### INSERT INTO `test`.`auto_1`
### SET
###   @1=3
###   @2='c'
###   @3=3
### INSERT INTO `test`.`auto_1`
### SET
###   @1=4
###   @2='d'
###   @3=4

主库在开启 GIPK 后,创建表后 Binlog 中也会有创建 my_row_id 语句,说明可以解决该问题。

需要注意的是,一定要保证主备库的字段 invisible/visible 属性是相同的。

2.2 主从复制

若主库没有开启 GIPK 而从库开启,那么 GIPK 是否会生效?

经测试:主库未开启 GIPK 备库开启 GIPK,主库上创建无主键表,备库不会主动为其创建主键。

2.3 逻辑备份

mysqldump 8.0.30 版本提供 --skip-generated-invisible-primary-key 参数,如果不指定该参数,导出的 SQL 就会包含 my_row_id,如果指定则会忽略 my_row_id 字段。

2.4 其它限制

2.4.1 AUTO_INCREMENT 属性

my_row_id 已经占用表中唯一的 AUTO_INCREMENT 属性,无法再次指定自增属性。

ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

2.4.2 my_row_id 关键字

my_row_id 已经成为关键字,无法使用。

ERROR 4108 (HY000): Failed to generate invisible primary key. Column 'my_row_id' already exists.

参考文档

【1】https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-30.html#mysqld-8-0-30-gipk



相关文章

InnoDB秘籍:MVCC机制与行锁的深度探索(1)

前言事务的起源可以追溯到 6000 年以前,当时苏美尔人(Sumerians)就发明了事务处理和记录的方法。已知最早的记录是写在土块上的,上面写了皇家的税收、土地、谷物、牲畜、奴隶和黄金,明确地记下了...

MySQL运维实战之备份和恢复(8.4)xtrabackup恢复全量备份

恢复全量备份恢复全量备份大致可以分成以下几步:解压备份文件、prepare备份文件、将数据copy到目标实例相关目录、启动数据库实例。解压文件如果备份时使用了xbstream,需要先解压备份文件。我们...

docker网络介绍

docker网络介绍

一、docker网络介绍安装docker时,会自动创建三个网络。可以使用docker network ls命令列出这些网络Docker内置这三个网络,运行容器时,可以使用--network标志来指定容...

MySQL 函数触发隐式转换应对策略

前言MySQL 中,当 SQL 索引字段使用了函数的话,会出现隐式转换的问题,导致索引失效,从而导致 SQL 执行效率变慢。本篇文章介绍 MySQL 不同版本此类问题的应对策略。1. 环境介绍以下是本...

CDP实操--配置HBase的Ranger策略验证(三)

CDP实操--配置HBase的Ranger策略验证(三)

1.1HBase的Ranger策略验证确保HBase的配置页面里已经勾选了“Ranger Service”在terminal中,kerberos登录到hbase,用如下命令登录hbase shellc...

oracle手工管理的不完全恢复

一)使用当前控制文件做不完全恢复示例1: 恢复过去某个时间点误删除的table(基于时间点的不完全恢复)前提:在这个状态下先在OS下做一个数据文件和控制文件的冷备。SQL> shutdown i...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。