文档中心>云数据库 MySQL>故障处理>隐藏主键相关报错处理

隐藏主键相关报错处理

最近更新时间:2026-06-30 16:16:09

我的收藏
本文为您介绍云数据库 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)

将 GIPK 替换为自定义主键

将已有列升级为主键

操作描述: 将原表中已经含有的一个字段设置为主键。
报错 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。

相关文档