MySQL8.0新特性之不可见主键的使用

 更新时间:2024年04月24日 09:50:50   作者:不剪发的Tony老师  
MySQL8.0.30版本引入不可见主键,它可以自动为没有显式指定主键的 InnoDB 表创建一个不可见的主键,本文主要介绍了MySQL8.0新特性之不可见主键的使用,具有一定的参考价值,感兴趣的可以了解一下

数据库设计通常需要满足一定的范式要求,其中主键更是最基本的要求。不过,数据库管理系统却允许我们创建没有主键的表。这样的表在 MySQL 中会带来查询性能低下、复制延迟甚至无法实现高可用配置等问题。

为此,MySQL 8.0.30 版本引入了一个新的功能,叫做不可见主键(Generated Invisible Primary Keys),它可以自动为没有显式指定主键的 InnoDB 表创建一个不可见的主键。

不可见主键

MySQL 通过系统变量 sql_generate_invisible_primary_key 控制是否启用 GIPK 特性,该变量的默认设置为 OFF。

以下示例创建了两个表,都没有指定主键。

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)

创建 auto_0 表时,sql_generate_invisible_primary_key 设置为 OFF;创建 auto_1 表时,sql_generate_invisible_primary_key 设置为 ON。

使用 SHOW CREATE TABLE 语句查看两个表的区别:

mysql> SHOW CREATE TABLE auto_0\G
*************************** 1. row ***************************
       Table: auto_0
Create Table: CREATE TABLE `auto_0` (
  `c1` varchar(50) DEFAULT NULL,
  `c2` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE auto_1\G
*************************** 1. row ***************************
       Table: auto_1
Create Table: CREATE TABLE `auto_1` (
  `my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */,
  `c1` varchar(50) DEFAULT NULL,
  `c2` 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)

MySQL 自动为 auto_1 创建了一个不可见字段 my_row_id,并且将其设置为主键。

不可见字段也叫做隐藏字段,是 MySQL 8.0.23 版本增加的新功能。作为不可见字段,my_row_id 不会出现在 SELECT * 或者 TABLE 语句的结果中,查询该字段必须显式指定它的名字。

这种情况下,系统默认增加的不可见主键字段名称固定为 my_row_id,因此我们不能在创建表时指定其他字段名为 my_row_id,除非同时将其指定为主键。

修改属性

当我们启用了 GIPK 功能时,不可见主键 my_row_id 不能使用 ALTER TABLE 语句进行修改,只能设置它的可见属性。以下命令将 auto_1 表的不可见主键设置为可见字段:

mysql> ALTER TABLE auto_1 ALTER COLUMN my_row_id SET VISIBLE;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW CREATE TABLE auto_1\G
*************************** 1. row ***************************
       Table: auto_1
Create Table: CREATE TABLE `auto_1` (
  `my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `c1` varchar(50) DEFAULT NULL,
  `c2` 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.01 sec)

当我们启用了 GIPK 功能时,如果删除不可见主键会导致以下任意情况发生,都不允许删除不可见主键:

  • 该表没有主键;
  • 删除主键而保留主键字段。

另外,GIPK 功能只支持 InnoDB 存储引擎,当我们使用 ALTER TABLE 语句修改这种表的存储引擎时,仍然会保留字段和主键约束,但是它会变成普通的主键字段。

字典信息

默认情况下,SHOW CREATE TABLE、SHOW COLUMNS 以及 SHOW INDEX 命令都会显示不可见主键信息。同时,information_schema 数据库中的 COLUMNS 和 STATISTICS 表中也包含了不可见主键字段。这一行为可以通过系统变量 show_gipk_in_create_table_and_information_schema 进行控制,默认值为 ON。

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

此时,我们查询系统表 COLUMNS 可以返回 auto_1 中的不可见主键 my_row_id:

mysql> SELECT COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE, COLUMN_KEY
    -> FROM INFORMATION_SCHEMA.COLUMNS
    -> WHERE TABLE_NAME = "auto_1";
+-------------+------------------+-----------+------------+
| COLUMN_NAME | ORDINAL_POSITION | DATA_TYPE | COLUMN_KEY |
+-------------+------------------+-----------+------------+
| my_row_id   |                1 | bigint    | PRI        |
| c1          |                2 | varchar   |            |
| c2          |                3 | int       |            |
+-------------+------------------+-----------+------------+
3 rows in set (0.01 sec)

如果将系统变量 show_gipk_in_create_table_and_information_schema 设置为 OFF,再次查询系统表 COLUMNS,不会显示不可见主键字段:

mysql> SET show_gipk_in_create_table_and_information_schema = OFF;
Query OK, 0 rows affected (0.00 sec)

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

mysql> SELECT COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE, COLUMN_KEY
    -> FROM INFORMATION_SCHEMA.COLUMNS
    -> WHERE TABLE_NAME = "auto_1";
+-------------+------------------+-----------+------------+
| COLUMN_NAME | ORDINAL_POSITION | DATA_TYPE | COLUMN_KEY |
+-------------+------------------+-----------+------------+
| c1          |                2 | varchar   |            |
| c2          |                3 | int       |            |
+-------------+------------------+-----------+------------+
2 rows in set (0.00 sec)

复制与备份

系统变量 sql_generate_invisible_primary_key 的配置不会被复制,复制应用线程会忽略该变量。这就意味着源节点的设置不会对副本产生影响。从 MySQL 8.0.32 版本开始,我们可以在 CHANGE REPLICATION SOURCE TO 语句使用 REQUIRE_TABLE_PRIMARY_KEY_CHECK = GENERATE 选项设置副本节点启用 GIPK 功能,为指定复制渠道中的那些没有主键的表自动增加不可见主键。

对于 CREATE TABLE … SELECT 语句,GIPK 支持基于行的复制选项,此时二进制日志中包含了 GIPK 定义,可以正确地复制。如果是基于语句的复制,CREATE TABLE … SELECT 不支持 sql_generate_invisible_primary_key = ON。

如果启用了 GIPK 功能,使用 mysqldump 备份或者还原数据时,可以通过 --skip-generated-invisible-primary-key 选项排除 GIPK 信息。

到此这篇关于MySQL8.0新特性之不可见主键的使用的文章就介绍到这了,更多相关MySQL8.0 不可见主键内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 批量替换 MySQL 指定字段中的字符串

    批量替换 MySQL 指定字段中的字符串

    批量替换 MySQL 指定字段中的字符串是数据库应用中很常见的需求,但是有很多初学者在遇到这种需求时,通常都是用脚本来实现;其实,MySQL 内置的有批量替换语法,效率也会高很多;想了解具体方法,继续阅读本文吧 :)
    2009-09-09
  • Mysql inner join on的用法实例(必看)

    Mysql inner join on的用法实例(必看)

    下面小编就为大家带来一篇Mysql inner join on的用法实例(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 10个mysql中select语句的简单用法

    10个mysql中select语句的简单用法

    本篇文章主要讲述的是MySQL SELECT句法的简单分析,我们大家都知道MySQL数据库是我们大家经常使用的数据库,其相关的应用也是备受关注的,那么以下的文章主要是对MySQL SELECT句法的简单分析。
    2014-08-08
  • CentOS7编译安装MySQL5.7.24的教程详解

    CentOS7编译安装MySQL5.7.24的教程详解

    这篇文章主要介绍了CentOS7编译安装MySQL5.7.24的教程,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-12-12
  • MySQL 函数索引的优化方案

    MySQL 函数索引的优化方案

    这篇文章主要介绍了MySQL 函数索引及优化方案的相关资料,帮助大家更好的理解和学习MySQL,感兴趣的朋友可以了解下
    2020-09-09
  • MySQL所支持的数据类型与表字段约束类型的学习教程

    MySQL所支持的数据类型与表字段约束类型的学习教程

    这篇文章主要介绍了MySQL所支持的数据类型与表字段约束类型的学习教程,是MySQL入门学习中的基础知识,需要的朋友可以参考下
    2015-12-12
  • 浅谈MySQL next-key lock 加锁范围

    浅谈MySQL next-key lock 加锁范围

    我们知道MYSQL NEXT-KEY LOCK是用来防止幻读,那么MySQL next-key lock 加锁范围是多少,很多人都不知道,本文就来详细的介绍一下
    2021-06-06
  • MySQL 5.7.17 免安装版本的安装配置

    MySQL 5.7.17 免安装版本的安装配置

    这篇文章主要为大家详细介绍了MySQL 5.7.17 免安装版本的安装配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • 超越MySQL 对流行数据库进行分支的知识小结

    超越MySQL 对流行数据库进行分支的知识小结

    尽管MySQL是最受欢迎的程序之一,但是许多开发人员认为有必要将其拆分成其他项目,并且每个分支项目都有自己的专长。该需求,以及 Oracle 对核心产品增长缓慢的担忧,导致出现了许多开发人员感兴趣的子项目和分支
    2012-01-01
  • MySQL系统及自定义变量方式

    MySQL系统及自定义变量方式

    这篇文章主要介绍了MySQL系统及自定义变量方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04

最新评论