一、概述
作为 MySQL DBA ,相信大家都经历过在复制模式下,如果没有主键,遇到 load data ,大事务,ddl 等有大量表数据行扫描的行为时,会带来严重的主从延迟,给数据库稳定性和数据一致性带来隐患。

MySQL 8.0.30 新版本为我们提供了一个新特性 -(Generated Invisible Primary Keys)简称 GIPK 。当开启GIPK模式后,MySQL 会在没有显示定义主键的InnoDB表上自动生成不可见的主键。

二、参数配置
GIPK 由参数 sql_generate_invisible_primary_key 控制,默认关闭,表示禁用,如果需要使用该特性,则需显式开启。
mysql> show variables like 'sql_generate_invisible_primary_key';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| sql_generate_invisible_primary_key | OFF |
+------------------------------------+-------+
1 row in set (0.02 sec)

mysql> set sql_generate_invisible_primary_key=on;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'sql_generate_invisible_primary_key';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| sql_generate_invisible_primary_key | ON |
+------------------------------------+-------+
1 row in set (0.01 sec)

三、功能验证:
现在分别在关闭和开启该特性下创建两个无主键表:
创建一张无主键的表t1:
mysql> create table t1(id int ,c1 int);
Query OK, 0 rows affected (0.00 sec)
mysql> show create table t1 \G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int DEFAULT NULL,
`c1` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

开启 GIPK 并创建无主键表 t2 。
mysql> set sql_generate_invisible_primary_key=on;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'sql_generate_invisible_primary_key';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| sql_generate_invisible_primary_key | ON |
+------------------------------------+-------+
1 row in set (0.00 sec)

mysql> create table t2(id int ,c1 int);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t2 \G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */,
`id` int DEFAULT NULL,
`c1` int DEFAULT NULL,
PRIMARY KEY (`my_row_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
我们可以通过 show create table 发现 t2 的表结构,出现一个名为 my_row_id 的不可见主键。

分别在两个表插入数据:
mysql> insert into t1 values(1,1),(2,2),(3,3);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from t1;
+------+------+
| id | c1 |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+
3 rows in set (0.00 sec)
mysql> insert into t2 values(1,1),(2,2),(3,3);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from t2;
+------+------+
| id | c1 |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+
3 rows in set (0.00 sec)

直接通过 select * table_name 查询表时,t2 和普通表t1没有差异。 因为 GIPK 是基于不可见列实现的,如果我们显式指定访问 my_row_id ,则可以查看到隐藏的主键 my_row_id。
mysql> select my_row_id,id,c1 from t2;
+-----------+------+------+
| my_row_id | id | c1 |
+-----------+------+------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
+-----------+------+------+
3 rows in set (0.00 sec)
所以,从业务程序访问数据库的来看,开启 GIPK 对业务是透明的。

四、表结构变更注意事项:
当开启 GIPK 特性时,MySQL 生成的主键不能更改,只能在 VISIBLE 和 INVISIBLE 之间进行切换。比如:
使 GIPK 主键可见: alter table TALBE_NAME alter column my_row_id set visible;
mysql> alter table t2 alter column my_row_id set visible;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table t2 \G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT, ### 显式可见
`id` int DEFAULT NULL,
`c1` int DEFAULT NULL,
PRIMARY KEY (`my_row_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

### 而且可以被直接查询到
mysql> select * from t2;
+-----------+------+------+
| my_row_id | id | c1 |
+-----------+------+------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
+-----------+------+------+
3 rows in set (0.00 sec)

关闭可见性 : alter table TABLE_NAME alter column my_row_id set invisible;
mysql> alter table t2 alter column my_row_id set invisible;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table t2 \G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */,
`id` int DEFAULT NULL,
`c1` int DEFAULT NULL,
PRIMARY KEY (`my_row_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

再次通过select * 查询则看不到 my_row_id
mysql> select * from t2;
+------+------+
| id | c1 |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+
3 rows in set (0.00 sec)

当开启 GIPK 之后 ,my_row_id 是系统关键字,我们创建无主键的表时,不能包含名为 my_row_id 的字段 。
mysql> create table t3(my_row_id int not null ,c1 int);
ERROR 4108 (HY000): Failed to generate invisible primary key. Column 'my_row_id' already exists.

但MySQL 允许创建包含名为 my_row_id 的主键的表 :
mysql> create table t5(my_row_id int not null auto_increment primary key ,c1 int);
Query OK, 0 rows affected (0.01 sec)

当开启 GIPK 模式时,不能直接删除不可见主键。必须显式增加一个新的主键然后再删除 GIPK
mysql> alter table t2 drop PRIMARY KEY;
ERROR 1235 (42000): This version of MySQL doesn't yet support 'existing primary key drop without adding a new primary key. In @@sql_generate_invisible_primary_key=ON mode table should have a primary key. Please add a new primary key to be able to drop existing primary key.'

mysql> alter table t2 drop PRIMARY KEY,add primary key(id);
ERROR 4111 (HY000): Please drop primary key column to be able to drop generated invisible primary key.

mysql> alter table t2 drop column my_row_id,add primary key(id);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0

五、主从复制注意事项:
需要注意的是 set sql_generate_invisible_primary_key=on|off 并不会被复制到从库,主库上开启该特性的话,从库并不会开启 GIPK 。也就是说从库也不会为任何在源库上没有创建主键的表创建主键。
下面测试一下,当主库关闭该特性,从库开启这个特性时的情况:
在 master 上关闭该特性并且创建无主键表t3
mysql> set sql_generate_invisible_primary_key=off;
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql>show variables like 'sql_generate_invisible_primary_key';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| sql_generate_invisible_primary_key | OFF |
+------------------------------------+-------+
1 row in set (0.00 sec)

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1 |
| t2 |
| t4 |
| t5 |
+----------------+
5 rows in set (0.00 sec)

mysql> create table t3(id int ,c1 int);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t3\G
*************************** 1. row ***************************
Table: t3
Create Table: CREATE TABLE `t3` (
`id` int DEFAULT NULL,
`c1` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

在从库上开启该特性
slave1 [localhost:22032]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1 |
| t2 |
| t3 |
| t4 |
| t5 |
+----------------+
5 rows in set (0.00 sec)
slave1 [localhost:22032]> set sql_generate_invisible_primary_key=on;
Query OK, 0 rows affected (0.00 sec)
slave1 [localhost:22032]> show variables like 'sql_generate_invisible_primary_key';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| sql_generate_invisible_primary_key | ON |
+------------------------------------+-------+
1 row in set (0.00 sec)
slave1 [localhost:22032]> show create table t3\G
*************************** 1. row ***************************
Table: t3
Create Table: CREATE TABLE `t3` (
`id` int DEFAULT NULL,
`c1` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
结果: 主库关闭 GIPK ,从库开启 GIPK ,源库上创建无主键表,从库上并不会主动为该表创建主键。

六、逻辑备份注意事项:
大多数实例会进行逻辑备份,如果 开启GIPK 模式时,MySQL 8.0.30 版本的 mysqldump 提供的 --skip-generated-invisible-primary-key 选项会忽略 GIPK 信息。简单来说,mysqldump 时 不带该参数,逻辑导出的数据会包含隐式主键,如果带上该参数,则不带隐式主键。

七、限制
只支持 InnoDB 存储引擎。
支持 row 模式复制,不支持 statement 模式复制。
my_row_id 成为系统关键字。

八、总结
总体而言,该特性绝对是强需求。像把MySQL只当做一个存数据的容器时,很多开发并不会创建主键,像BI开发人员,所以现实情况是,什么样的情况都可能会发生。 MySQL 数据库稳定性也因为很多无主键的表,导致很多故障发生,对于自建场景尤其是没有严格审核流程的开发团队 ,该特性更能提升数据库系统稳定性和安全性。

【昌哥IT课堂】MySQL8.0新特性之不可见主键
官方文档中文翻译版本下载地址:
https://cloud.189.cn/t/eUBJJzaeqUJ3 (访问码:qg7d)

微信公众号视频播放地址:
https://mp.weixin.qq.com/s/9v-e6mZHAHB8Q4uoWQlonw

文章看完了,如果觉得本文对您的工作或生活有用,希望分享给你身边的朋友,一起学习,共同进步哈~~~

欢迎关注我的公众号【数库信息技术】,你的关注是我写作的动力源泉

各大平台都可以找到我:
————————————————————————————
公众号:数库信息技术
墨天轮:https://www.modb.pro/u/427810
百家号:https://author.baidu.com/home/1780697309880431
CSDN :https://blog.csdn.net/rscpass
51CTO: https://blog.51cto.com/u_16068254
博客园:https://www.cnblogs.com/shukuinfo
知乎:https://www.zhihu.com/people/shukuinfo
————————————————————————————

【昌哥IT课堂】MySQL8.0新特性之不可见主键的更多相关文章

  1. 跨时代的MySQL8.0新特性解读

    目录 MySQL发展历程 MySQL8.0新特性 秒级加列 性能提升 文档数据库 SQL增强 共用表表达式(CTEs) 不可见索引(Invisible Indexes) 降序索引(Descending ...

  2. 深入解读MySQL8.0 新特性 :Crash Safe DDL

    前言 在MySQL8.0之前的版本中,由于架构的原因,mysql在server层使用统一的frm文件来存储表元数据信息,这个信息能够被不同的存储引擎识别.而实际上innodb本身也存储有元数据信息.这 ...

  3. MySQL-08 MySQL8.0新特性

    性能 MySQL 8.0 在一定的用户访问条件下,速度要比 MySQL 5.7 快 2 倍.MySQL 8.0 在以下方面带来了更好的性能:读/写工作负载.IO 密集型工作负载.以及高竞争(" ...

  4. MySQL8.0新特性实验1

    Server层,选项持久化 mysql> show variables like '%max_connections%';+------------------------+-------+| ...

  5. mysql8.0 新特性,对json类型的常用操作

    mysql8 新特性-json数据类型操作 -- 根据key(可多个)获取value SELECT JSON_EXTRACT('{"id": 14, "name" ...

  6. Mysql8.0新特性【详细版本】

    1.  账户与安全 用户创建与授权 之前:创建用户并授权 1 grant all privileges on *.* to 'myuser'@'%' identified by '3edc#EDC'; ...

  7. MySQL8.0 新特性 Hash Join

    概述&背景 MySQL一直被人诟病没有实现HashJoin,最新发布的8.0.18已经带上了这个功能,令人欣喜.有时候在想,MySQL为什么一直不支持HashJoin呢?我想可能是因为MySQ ...

  8. MySQL 8 新特性之自增主键的持久化

    自增主键没有持久化是个比较早的bug,这点从其在官方bug网站的id号也可看出(https://bugs.mysql.com/bug.php?id=199).由Peter Zaitsev(现Perco ...

  9. MySQL8.0新特性——支持原子DDL语句

    MySQL 8.0开始支持原子数据定义语言(DDL)语句.此功能称为原子DDL.原子DDL语句将与DDL操作关联的数据字典更新,存储引擎操作和二进制日志写入组合到单个原子事务中.即使服务器在操作期间暂 ...

  10. MySQL8.0新特性总览

    1.消除了buffer pool mutex (Percona的贡献) 2.数据字典全部采用InnoDB引擎存储,支持DDL原子性.crash safe.metadata管理更完善(可以利用ibd2s ...

随机推荐

  1. win2003 密钥 vl_cd1_X13-46432.iso

    1.使用的 ISO为:cn_win_srv_2003_r2_enterprise_with_sp2_vl_cd1_X13-46432.iso 2.迅雷链接 ed2k://|file|cn_win_sr ...

  2. vue grid layout 设定某组件为最低位,其它子item无法拖拽超过

    逻辑:    设定某项X为底部    逻辑:    for 循环获取最低位的item Y的信息:i 和 y    如果i != X.i        initY = X.y        则调整X.y ...

  3. 【YashanDB知识库】stmt未close,导致YAS-00103 no free block in sql main pool part 0报错分析

    问题现象 问题单:YAS-00103 no free block in sql main pool part 0,YAS-00105 out of memory to allocate hash ta ...

  4. 开源文档管理系统 MinDoc 安装和使用教程

    说到文档管理,很多团队的文档管理都是一团糟,每个员工在自己本地写了各种 Word 文档.Excel 表格.甚至还有手写的便签,到处都是,找起来就像大海捞针.有些聪明的团队开始用飞书来管理团队文档,但是 ...

  5. 《放弃繁琐的if-else》开启Assert断言的新时代

    一.场景再现 我们平时在service操作数据库,难免会出现这种情况: if(null == result){ }else{ } 这样的代码会吞噬掉你有限的代码空间,虽然通俗易懂,但一旦爆炸式的袭来, ...

  6. 深入理解JavaScript中的try catch finally

    在日常开发中,我们经常使用try catch 来捕捉错误,来提升应用程序的健壮性,但是,大部分时候,只是惯性使用,很少静下来去深入理解一下try catch finally,所以本文将对try cat ...

  7. 【倒计时3天】“CSIG企业行”走进合合信息,大咖解密智能文档处理背后的底层技术及AI未来展望

    3月18日,由中国图象图形学会(CSIG)主办,合合信息.CSIG文档图像分析与识别专业委员会联合承办的"CSIG企业行"系列活动将正式举办,通过搭建学术界与企业交流合作平台,为企 ...

  8. EF Core – Unit of Work, DbContext, Transaction 概念解释

    前言 踩了一个坑, 下面是 2 个 scope 的调用, 第 1 和 3 是一个 Audit log filter action, 第 2 个是 controller. // open tran // ...

  9. 2How To Use Python On A Web Page With Jinja2 - Fla 21:30

    # localhost:5000/user/John @app.route("/user/<name>") def user(name): return render_ ...

  10. UsbHostManager解析

    UsbHostManager和UsbDeviceManager的区别在于,UsbDeviceManager是将手机作为一个设备,比如手机连上电脑,使用adb.mtp等:而UsbHostManager, ...