云数据库 MySQL 隐藏主键相关报错处理

这里说明云数据库 MySQL 开启隐藏主键特性后建表或改主键可能遇到的报错,以及如何正确查看、替换/移除隐藏主键或关闭该特性的处理方法。

相关产品
云数据库 MySQL 产品页,含版本规格、价格与购买入口。

一、背景

云数据库 MySQL 8.0 20221215(社区版本8.0.30)及后续的内核小版本中,支持了 GIPK(Generated Invisible Primary Keys,简称 GIPK)特性,云数据库 MySQL 5.7 暂不支持。若你在建表时未显式定义主键(Primary Key),系统会自动为表添加一个名为 my_row_id 的隐藏主键。添加隐藏主键后,如果你想使用 DDL 自定义新主键,可能会遇到报错。

二、报错信息

在 ALTER TABLE 语句中定义新的主键时,可能会遇到以下报错:

报错场景1:

Error 1068: Multiple primary key defined.

报错解释:自定义主键与隐藏主键冲突。

报错场景2:

Error 1075: Incorrect table definition; there can be only one auto column and it must be defined as a key.

报错解释:新的自增列与隐藏主键冲突。

在 CREATE TABLE 语句中定义新的主键时,可能会遇到以下报错:

报错场景3:

Error 4109: Failed to generate invisible primary key. Auto-increment column already exists.

报错解释:开启 GIPK 时,自增列未定义为主键索引。

三、查看 GIPK

由于 GIPK 有“隐藏列”属性,你无法直接通过 show create table 查看到 GIPK,请按照以下方法查看 GIPK 。

1. 设置参数 sql_generate_invisible_primary_key 值为 ON。

2. 设置完成后,即可在 show create table 中看到隐藏主键 my_row_id。

mysql> show create table tb1;+——-+——————————————————————————————————————————————————————————————————————————-+| Table | Create Table |+——-+——————————————————————————————————————————————————————————————————————————-+| tb1 | CREATE TABLE `tb1` ( `my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */, `id` int DEFAULT NULL, `c` varchar(16) DEFAULT NULL, PRIMARY KEY (`my_row_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+——————————————————————————————————————————————————————————————————————————-+1 row in set (0.01 sec)

3. 替换主键不需要关闭 GIPK,保持开启即可。

mysql> select @@sql_generate_invisible_primary_key;+————————————–+| @@sql_generate_invisible_primary_key |+————————————–+| 1 |+————————————–+1 row in set (0.00 sec)

四、将已有列升级为主键

操作描述: 将原表中已经含有的一个字段设置为主键。

报错 SQL 示例:

alter table table_name add primary key(id);

报错详情:Error 1068: Multiple primary key defined。

变更前表结构示例: 含有隐藏主键列 my_row_id。

mysql> show create table tb1;+——-+——————————————————————————————————————————————————————————————————————————-+| Table | Create Table |+——-+——————————————————————————————————————————————————————————————————————————-+| tb1 | CREATE TABLE `tb1` ( `my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */, `id` int DEFAULT NULL, `c` varchar(16) DEFAULT NULL, PRIMARY KEY (`my_row_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+——————————————————————————————————————————————————————————————————————————-+1 row in set (0.01 sec)

变更 SQL:

alter table tb1 drop column my_row_id, add primary key(id);

变更后表结构: 隐藏主键 my_row_id 被移除,id 为新主键。

mysql> show create table tb1;+——-+————————————————————————————————————————————–+| Table | Create Table |+——-+————————————————————————————————————————————–+| tb1 | CREATE TABLE `tb1` ( `id` int NOT NULL, `c` varchar(16) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+————————————————————————————————————————————–+1 row in set (0.00 sec)

五、新加一个主键列

操作描述: 新增一列作为主键。

报错 SQL 示例:

alter table table_name add column new_id bigint primary key;

相关报错:Error 1068: Multiple primary key defined。

变更前表结构示例:含有隐藏主键列 my_row_id。

mysql> show create table tb2;+——-+——————————————————————————————————————————————————————————————————————————-+| Table | Create Table |+——-+——————————————————————————————————————————————————————————————————————————-+| tb2 | CREATE TABLE `tb2` ( `my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */, `i` int DEFAULT NULL, `c` varchar(16) DEFAULT NULL, PRIMARY KEY (`my_row_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+——————————————————————————————————————————————————————————————————————————-+

变更 SQL:

加列并替换 GIPK,新列无额外要求,这里为你展示新加一个 BIGINT 属性的 new_id 列。

alter table table_name drop column my_row_id, add column new_id bigint primary key;

变更后表结构: 隐藏主键 my_row_id 被移除,new_id 为新主键。

mysql> show create table tb2;+——-+—————————————————————————————————————————————————————————————————+| Table | Create Table |+——-+—————————————————————————————————————————————————————————————————+| tb2 | CREATE TABLE `tb2` ( `i` int DEFAULT NULL, `c` varchar(16) DEFAULT NULL, `new_id` bigint unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`new_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+—————————————————————————————————————————————————————————————————+

六、新增自增列

操作描述: 新增一个自增列。

报错 SQL 示例:

alter table table_name add column new_id bigint unsigned not null auto_increment key;

报错详情:Error 1075: Incorrect table definition; there can be only one auto column and it must be defined as a key。

变更前表结构示例:含有隐藏主键列 my_row_id。

mysql> show create table tb3;+——-+——————————————————————————————————————————————————————————————————————————-+| Table | Create Table |+——-+——————————————————————————————————————————————————————————————————————————-+| tb3 | CREATE TABLE `tb3` ( `my_row_id` bigint unsigned NOT NULL AUTO_INCREMENT /*!80023 INVISIBLE */, `i` int DEFAULT NULL, `c` varchar(16) DEFAULT NULL, PRIMARY KEY (`my_row_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+——————————————————————————————————————————————————————————————————————————-+

变更 SQL:加自增列 new_id 并替换 GIPK。

alter table table_name drop column my_row_id, add column new_id bigint unsigned not null auto_increment key;

变更后表结构:隐藏主键 my_row_id 被移除,new_id 为新主键。

mysql> show create table tb3;+——-+—————————————————————————————————————————————————————————————————+| Table | Create Table |+——-+—————————————————————————————————————————————————————————————————+| tb3 | CREATE TABLE `tb3` ( `i` int DEFAULT NULL, `c` varchar(16) DEFAULT NULL, `new_id` bigint unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`new_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+—————————————————————————————————————————————————————————————————+

七、创建含有自增列的表

操作描述:创建一个含有自增列的表。

报错 SQL 示例:

create table table_name ( id bigint unsigned NOT NULL AUTO_INCREMENT UNIQUE KEY, c varchar(16));

错误详情:Error 4109: Failed to generate invisible primary key. Auto-increment column already exists。

变更 SQL:使用 PRIMARY KEY 或 KEY 关键字。

create table table_name ( id bigint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, c varchar(16));

变更后表结构:id 为新主键。

mysql> show create table tb4;+——-+—————————————————————————————————————————————————————————————————+| Table | Create Table |+——-+—————————————————————————————————————————————————————————————————+| tb4 | CREATE TABLE `tb4` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `c` varchar(16) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+——-+—————————————————————————————————————————————————————————————————+

八、打开 GIPK 创建分区表

操作描述: 创建一个无主键的分区表。

报错 SQL 示例:

CREATE TABLE tb5 (f1 INT, f2 DATE) PARTITION BY KEY(f2) PARTITIONS 2;

错误详情:Error 1235: This version of MySQL doesn't yet support 'generating invisible primary key for the partitioned tables。

变更操作:将参数 sql_generate_invisible_primary_key 的值设置为 OFF。

九、相关文档

设置实例参数

赞 (0)
上一篇 4天前
下一篇 4天前