本文为您介绍云数据库 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_nameadd 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_namedrop 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_nameadd 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_namedrop 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。