文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  產生的隱形主鍵

15.1.20.11 產生的隱形主鍵

MySQL 8.4 支援為任何在建立時沒有明確主鍵的 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 以及該欄位的主鍵。由於建立 auto_0sql_generate_invisible_primary_keyOFF,因此沒有對該資料表執行此類新增作業。

當伺服器將主鍵新增至資料表時,欄位和索引鍵名稱一律為 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 的輸出中,並且在資訊結構描述 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 之後,無法再在 COLUMNS 資料表中看到 my_row_id,如下所示

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 資訊在程式的輸出中排除。