文档首页
MySQL 9.0 参考手册
相关文档 下载此手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  生成的不可见主键

15.1.20.11 生成的不可见主键

MySQL 9.0 支持为任何没有显式主键的 InnoDB 表生成不可见主键。当 sql_generate_invisible_primary_key 服务器系统变量设置为 ON 时,MySQL 服务器会自动向所有此类表添加一个生成的不可见主键 (GIPK)。此设置对使用除 InnoDB 之外的任何其他存储引擎创建的表没有影响。

默认情况下,sql_generate_invisible_primary_key 的值为 OFF,这意味着自动添加 GIPK 已禁用。为了说明这将如何影响表创建,我们首先创建两个相同的表,它们都没有主键,唯一的区别是第一个表 (auto_0) 在 sql_generate_invisible_primary_key 设置为 OFF 时创建,而第二个表 (auto_1) 在将其设置为 ON 后创建,如下所示

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 语句的输出,以查看表实际创建方式的差异

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)

由于 auto_1 在创建时没有通过 CREATE TABLE 语句指定主键,所以设置 sql_generate_invisible_primary_key = ON 会导致 MySQL 为该表添加不可见列 my_row_id 以及该列上的主键。由于 sql_generate_invisible_primary_key 在创建 auto_0 时为 OFF,因此该表没有进行任何此类添加操作。

当服务器为表添加主键时,列名和键名始终为 my_row_id。因此,当以这种方式启用生成不可见主键时,您无法创建包含名为 my_row_id 的列的表,除非表创建语句还指定了显式主键。(在这种情况下,您不需要将列或键命名为 my_row_id。)

my_row_id 是一个不可见列,这意味着它不会显示在 SELECT *TABLE 的输出中;必须通过名称显式选择该列。请参阅 第 15.1.20.10 节,“不可见列”

当启用 GIPK 时,生成的不可见主键只能被修改为在 VISIBLEINVISIBLE 之间切换。要使 auto_1 上生成的不可见主键可见,请执行以下 ALTER TABLE 语句

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)

要使此生成的不可见主键再次不可见,请执行 ALTER TABLE auto_1 ALTER COLUMN my_row_id SET INVISIBLE

生成的不可见主键默认始终不可见。

无论何时启用 GIPK,如果以下两个条件中的任何一个会导致以下情况,则您都无法删除生成的不可见主键

  • 表没有主键。

  • 删除了主键,但没有删除主键列。

sql_generate_invisible_primary_key 的效果仅适用于使用 InnoDB 存储引擎的表。您可以使用 ALTER TABLE 语句更改具有生成的不可见主键的表的存储引擎;在这种情况下,主键和列会保留在原位,但表和键不再接收任何特殊处理。

默认情况下,GIPK 会显示在 SHOW CREATE TABLESHOW COLUMNSSHOW INDEX 的输出中,并且在 Information Schema 的 COLUMNSSTATISTICS 表中可见。您可以通过将 show_gipk_in_create_table_and_information_schema 系统变量设置为 OFF 来使生成的不可见主键在这种情况下隐藏起来。默认情况下,此变量为 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 表的查询可以看出,my_row_idauto_1 的列中是可见的

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 之后,my_row_idCOLUMNS 表中将不再可见,如下所示

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 的设置不会被复制,并且会被复制应用线程忽略。这意味着此变量在源上的设置对副本没有影响。您可以通过在 CHANGE REPLICATION SOURCE TO 语句中使用 REQUIRE_TABLE_PRIMARY_KEY_CHECK = GENERATE 来使副本为在给定复制通道上没有主键的表添加 GIPK。

GIPK 与 CREATE TABLE ... SELECT 的基于行的复制一起使用;在这种情况下,写入二进制日志的信息包括 GIPK 定义,因此会正确复制。在 sql_generate_invisible_primary_key = ON 的情况下,不支持 CREATE TABLE ... SELECT 的基于语句的复制。

在创建或导入使用 GIPK 的安装的备份时,可以排除生成的不可见主键列和值。--skip-generated-invisible-primary-key 选项用于 mysqldump 会导致 GIPK 信息在程序的输出中被排除。