Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Generated Invisible Primary Keys

15.1.20.11 生成的不可见主键

MySQL 8.4 支持对任何InnoDB表创建生成不可见主键。只要服务器系统变量sql_generate_invisible_primary_key设置为ON, MySQL 服务器将自动添加一个生成不可见主键(GIPK)到任何这样的表。

默认情况下,sql_generate_invisible_primary_key的值是OFFauto_0)使用sql_generate_invisible_primary_key设置为OFFauto_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时没有指定主键,设置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节,“不可见列”

当GIPKs启用时,生成的主键不能被修改,只能切换为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

生成的隐形主键默认总是隐形的。

当GIPKs启用时,您不能删除生成的主键,如果满足以下两个条件之一:

  • 表中没有主键了。

  • 主键被删除,但主键列还在。

sql_generate_invisible_primary_key的效果只对使用InnoDB存储引擎的表生效。您可以使用ALTER TABLE语句更改使用生成隐形主键的表的存储引擎;在这种情况下,主键和列仍然保留,但表和键不再享受特殊处理。

默认情况下,GIPKs 在SHOW CREATE TABLESHOW COLUMNSSHOW INDEX 的输出中显示,并且在信息架构中的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的设置不被复制,且被复制线程忽略。这意味着源服务器上的这个变量设置对副本没有影响。您可以使用 REQUIRE_TABLE_PRIMARY_KEY_CHECK = GENERATE 作为CHANGE REPLICATION SOURCE TO 语句在给定的复制通道上让副本添加GIPK。

GIPK与CREATE TABLE ... SELECT 的行级别复制一起工作;在这种情况下,二进制日志中写入的语句包括GIPK定义,因此可以正确地复制。基于语句的CREATE TABLE ... SELECT 复制不支持sql_generate_invisible_primary_key = ON.

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