- 1. GIPKs特性簡介 - 2. GIPKs特性的作用 - 3. 玩轉GIPKs > GIPKs解決了歷史難題 ## 1. GIPKs特性簡介 從MySQL 8.0.30開始,新引入一個叫做GPIKs的特性,其全稱是 **Generated Invisible Primary Keys**,簡 ...
-
- GIPKs特性簡介
-
- GIPKs特性的作用
-
- 玩轉GIPKs
GIPKs解決了歷史難題
1. GIPKs特性簡介
從MySQL 8.0.30開始,新引入一個叫做GPIKs的特性,其全稱是 Generated Invisible Primary Keys,簡言之就是 自動生成隱含的主鍵列,更完整的說法是:啟用GIPKs後,當新建的InnoDB表沒有顯式主鍵時,會自動創建一個不可見的主鍵列 my_row_id
,這個列會被定義為 bigint unsigned NOT NULL AUTO_INCREMENT
,並且是不可見的(INVISIBLE
)。
2. GIPKs特性的作用
實際上這個特性在有些分支版本上早就已經實現了,這個需求也是非常迫切,MySQL官方對這個特性的支持雖遲但到,積極意義還是很大滴,解決了幾個歷史難題:
- DBA無需再和開發battle,強調一定要有顯式自增主鍵列。當然了,個別情況下非要顯式指定非自增列(例如選擇UUID/VARCHAR類型列)做主鍵的,DBA也無可奈何啊。
- 在MGR架構中,也不用要求每個InnoDB表都必須要有顯式定義的主鍵列。
上述這兩種情況下,都可以從GIPKs特性中獲益,會自動創建隱含的 my_row_id
主鍵列。
GIPKs特性帶來的一點點不便是,當我們想要顯式創建一個名為 my_row_id
的列名時,會報錯,不讓創建,因為被GIPKs特性給當做保留關鍵字了,例如:
greatsql> create table t2(
id bigint unsigned not null auto_increment,
my_row_id int NOT NULL);
ERROR 4109 (HY000): Failed to generate invisible primary key. Auto-increment column already exists.
需要註意的是,在傳統主從複製或MGR架構中,GIPKs特性的設置值不會被覆制到從節點,僅影響當前節點。不過,這完全不影響主從複製或MGR的正常工作,也就是說:在主節點上創建無顯式定義主鍵列的表數據,可以正常複製到從節點。前提條件是設置 binlog_format = row
,在MGR中,要求binlog必須採用row格式。
另外,mysqldump
中也相應增加了新選項 --skip-generated-invisible-primary-key
,用於指定備份時是否要忽略隱含主鍵列。
3. 玩轉GIPKs
下麵我們在MGR環境中舉慄說明怎麼玩轉GIPKs特性:
# 當前使用 GreatSQL 8.0.32-24 版本
greatsql> \s
..
Server version: 8.0.32-24 GreatSQL, Release 24, Revision 3714067bc8c
...
# 在MGR環境中測試
greatsql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 2adec6d2-febb-11ed-baca-d08e7908bcb1 | 192.168.5.160 | 3307 | ONLINE | SECONDARY | 8.0.32 | XCom |
| group_replication_applier | 2f68fee2-febb-11ed-b51e-d08e7908bcb1 | 192.168.5.160 | 3308 | ONLINE | ARBITRATOR | 8.0.32 | XCom |
| group_replication_applier | 5e34a5e2-feb6-11ed-b288-d08e7908bcb1 | 192.168.5.160 | 3306 | ONLINE | PRIMARY | 8.0.32 | XCom |
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
# 確認啟用GIPKs特性
greatsql> show variables like 'sql_generate_invisible_primary_key';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| sql_generate_invisible_primary_key | ON |
+------------------------------------+-------+
# 新建表,未顯式指定主鍵列
greatsql> create table t1 ( id int not null, c1 varchar(10) not null, unique key(id));
greatsql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */,
`id` int NOT NULL,
`c1` varchar(10) NOT NULL,
PRIMARY KEY (`my_row_id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
可以看到,在建表時已經創建了唯一索引列(該索引列可以被選用作聚集索引),但由於沒顯式指定主鍵索引,所以還是會創建一個隱含的主鍵列 my_row_id
,這個隱含的主鍵列預設是不可見的,除非我們手動修改其可見性。
# 即便是 SELECT *,也無法讀取隱含的主鍵列
greatsql> select * from t1;
+----+----+
| id | c1 |
+----+----+
| 1 | c1 |
| 2 | c2 |
+----+----+
# 除非修改隱含主鍵列為可見
greatsql> alter table t1 alter column my_row_id set visible;
# 這時就能看到這個隱含主鍵列
greatsql> select * from t1;
+-----------+----+----+
| my_row_id | id | c1 |
+-----------+----+----+
| 1 | 1 | c1 |
| 2 | 2 | c2 |
+-----------+----+----+
# 再次查看表結構
greatsql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT,
`id` int NOT NULL,
`c1` varchar(10) NOT NULL,
PRIMARY KEY (`my_row_id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
# 還可以再次將其設置為不可見
greatsql> alter table t1 alter column my_row_id set invisible;
greatsql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */,
`id` int NOT NULL,
`c1` varchar(10) NOT NULL,
PRIMARY KEY (`my_row_id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
如果不想繼續使用該隱含列作為主鍵,可以執行類似下麵的SQL命令進行修改:
# 刪除隱含主鍵列、主鍵,並新建自定義的主鍵列
greatsql> alter table t1 drop column my_row_id, drop primary key, add aid bigint unsigned not null auto_increment primary key first;
# 再次查看表結構和查詢表數據
greatsql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`aid` bigint unsigned NOT NULL AUTO_INCREMENT,
`id` int NOT NULL,
`c1` varchar(10) NOT NULL,
PRIMARY KEY (`aid`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
greatsql> select * from t1;
+-----+----+----+
| aid | id | c1 |
+-----+----+----+
| 1 | 1 | c1 |
| 2 | 2 | c2 |
+-----+----+----+
可以看到,GIPKs特性還是很靈活實用的。
P.S,最新發佈的GreatSQL 8.0.32-24版本中,已經包含了該特性,可以放心使用。
全文完。
Enjoy GreatSQL