You need to enable JavaScript to run this app.
文档中心
云数据库 MySQL 版

云数据库 MySQL 版

复制全文
下载 pdf
功能
隐藏主键
复制全文
下载 pdf
隐藏主键
背景信息​
无主键表​
在 MySQL 数据库中,无主键表的创建会对高可用性架构引入较大风险:​
  • Binlog 同步机制失效 当发生全表数据更新或范围删除操作时,基于 Row 格式的 binlog 在从库回放过程中,由于缺乏聚簇索引,每条 binlog 事件都需要执行全表扫描定位数据。实测发现,百万级数据表的这类操作会导致主备同步延迟呈指数级增长。​
  • 存储引擎特性冲突 InnoDB 引擎的聚簇索引特性要求必须有唯一行标识。当表缺失显式主键时:​
  • 引擎自动生成的隐式 ROW_ID 不具备索引可见性。​
  • 二级索引叶子节点被迫指向隐式 ROW_ID,导致数据定位路径不可见且维护成本高昂。​
  • 每次 DML 操作实质上都退化为全表遍历。​
  • 高可用链路雪崩效应 无主键表引发的延迟具有自我恶化特性:​
  • 主库持续产生新 binlog 事件。​
  • 从库因全表扫描无法及时消费事件队列。​
  • 最终导致复制中断。​
  • 故障切换时出现数据不一致风险。​
解决办法​
  • 事后处理 - 重做备库​
  • 在无主键表已经产生后,在不改变表结构的情况下处理的办法,办法是设置主从延迟告警,并人工查看是否为无主键表造成,并通过工单重做备库,带来了额外的人力负担,不可持续。​
  • 事前处理 - 隐藏主键​
  • MySQL 社区 8.0.30 带来了隐藏主键(GIPK, i.e. Generated Invisible Primary Key)特性,可以识别 CREATE TABLE 建表语句中的无主键表,通过 MySQL 的「隐藏列」属性,给表添加一个用户不可见的主键索引。这样既可以对用户使用不造成影响,又可以解决无主键表的问题,让新建表不存在无主键的情况。​
云数据库 MySQL 版 GPIK 能力简介​
云数据库 MySQL 版在 8.0 社区版的基础上对社区的隐藏主键进行了若干优化,并在 MySQL 5.7 通过唯一索引实现了类似 GIPK 的功能。云数据库 MySQL 版在 MySQL 8.0、MySQL 8.4 和 MySQL 5.7 中提供的隐藏主键能力对比如下。​
​
GIPK属性​
MySQL 8.0/MySQL 8.4​
MySQL 5.7​
KEY 类型​
主键索引(Primary Key)​
bigint(20), auto_increment​
唯一索引(Unique Index)​
bigint(20), auto_increment​
主键列名称​
my_row_id​
byte_rds_ai_uk_row_id​
创建 GIPK 条件​
CREATE TABLE 语句无主键​
CREATE TABLE 语句无主键或唯一键​
用户新增 PK 后,是否自动 DROP 主键列​
是​
是​
用户 Select * 查询是否能选中 GIPK​
否​
否​
控制参数(session)​
sql_generate_invisible_primary_key​
loose_sql_generate_invisible_primary_key​
展示 GIPK 参数​
show_gipk_in_create_table_and_information_schema​
loose_show_gipk_in_create_table_and_information_schema​
​
支持版本​
  • MySQL 8.0 版本,且内核小版本为 MySQL 8.0.32_20240415 及以上。​
  • MySQL 5.7 版本,且内核小版本为 MySQL 5.7.32_20241015 及以上。​
  • MySQL 8.4 版本,且内核小版本为 MySQL 8.4.7_20260415 及以上。​
说明​
您可通过查看实例信息查看实例的内核小版本。如您的实例为 MySQL 5.7.32_20241015 或 MySQL 8.0.32_20241015 之前的版本,可手动升级实例内核小版本。​
使用方法​
打开隐藏主键​
修改实例参数为 ON。​
  • MySQL 8.0、MySQL 8.4:sql_generate_invisible_primary_key​
  • MySQL 5.7:loose_sql_generate_invisible_primary_key​
说明​
  • 以上两个参数非开放的可修改参数。如需修改,请提交工单联系技术支持。​
  • 在内核小版本为 20241215 及更新版本的实例中,以上两个参数的值默认为 ON。​
查看隐藏主键​
  • MySQL 5.7​
  • 会话级别打开 loose_show_gipk_in_create_table_and_information_schema 参数后可以在 show create table 中看到隐藏主键 byte_rds_ai_uk_row_id。​
​
mysql> set loose_show_gipk_in_create_table_and_information_schema=on;​
​
mysql> show variables like '%gipk%';​
+--------------------------------------------------------+-------+​
| Variable_name | Value |​
+--------------------------------------------------------+-------+​
| loose_show_gipk_in_create_table_and_information_schema | ON |​
+--------------------------------------------------------+-------+​
1 row in set (0.01 sec)​
​
mysql > show create table tt1;​
+-------+---------------------------------------------------------------------------------------------------+​
| Table | Create Table |​
+-------+---------------------------------------------------------------------------------------------------+​
| tt1 | CREATE TABLE tt1 (​
`byte_rds_ai_uk_row_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'BYTE_RDS_INVISIBLE',​
`f1` int DEFAULT NULL,​
`f2` int DEFAULT NULL,​
UNIQUE KEY (`byte_rds_ai_uk_row_id`)​
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 | ​
+-------+---------------------------------------------------------------------------------------------------+​
​
  • MySQL 8.0​
  • 会话级别打开 show_gipk_in_create_table_and_information_schema 参数后可以在 show create table 中看到隐藏主键 my_row_id。​
​
mysql> set show_gipk_in_create_table_and_information_schema=on;​
​
mysql> show variables like '%gipk%';​
+--------------------------------------------------+-------+​
| Variable_name | Value |​
+--------------------------------------------------+-------+​
| show_gipk_in_create_table_and_information_schema | ON |​
+--------------------------------------------------+-------+​
1 row in set (0.01 sec)​
​
mysql> show create table t00;​
+-------+-------------------------------------------------------------------------------+​
| Table | Create Table |​
+-------+-------------------------------------------------------------------------------+​
| t00 | CREATE TABLE `t00` (​
`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=utf8mb3 |​
+-------+-------------------------------------------------------------------------------+​
1 row in set (0.01 sec)​
​
  • MySQL 8.4​
  • 会话级别打开 show_gipk_in_create_table_and_information_schema 参数后可以在 show create table 中看到隐藏主键 my_row_id。​
​
mysql> set show_gipk_in_create_table_and_information_schema=on;​
mysql> show variables like '%gipk%';​
+--------------------------------------------------+-------+​
| Variable_name | Value |​
+--------------------------------------------------+-------+​
| show_gipk_in_create_table_and_information_schema | ON |​
+--------------------------------------------------+-------+​
1 row in set (0.01 sec)​
mysql> show create table t00;​
+-------+-----------------------------------------------------------------------------------+​
| Table | Create Table |​
+-------+-----------------------------------------------------------------------------------+​
| t00 | CREATE TABLE `t00` ( ​
`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=utf8mb3 |​
+-------+-----------------------------------------------------------------------------------+​
1 row in set (0.01 sec)​
​
DDL 兼容性一览表​
打开 GIPK 后,云数据库 MySQL 版对 DDL 的支持情况如下表所示。​
说明​
内核小版本为 20241015 或更新版本。​
CREATE TABLE​
​
描述​
DDL 示例​
MySQL 5.7​
MySQL 8.0​
MySQL 8.4​
建表 DDL 中有用户定义的 auto_increment列(不定义为索引)​
​
create table gipk_test(i int auto_increment, c varchar(255));​
​
不允许。​
ERROR 1075。​
原生行为,auto inc 必须为索引。​
​
​
建表 DDL 中有用户定义的 auto_increment 列(定义为索引)​
​
create table gipk_test(i int auto_increment unique key, c varchar(255));​
​
允许。​
​
​
建表 DDL 中使用 GIPK 预留列名,不作为隐藏主键(非 bigint NOT NULL AUTO_INCREMENT)​
​
create table gipk_test(`my_row_id` int auto_increment unique key, c varchar(255));​
​
不允许。​
不允许将byte_rds_ai_uk_row_id 作为列名。​
允许,但输出告警​
跳过 GIPK 创建,my_row_id 为普通列。​
​
使用 GIPK 相关 COMMENT​
​
create table gipk_test(i int COMMENT 'Implicit Primary Key by RDS', c varchar(255));​
​
允许。​
​
​
创建无主键分区表 DDL​
​
CREATE TABLE gipk_test (​
sale_id INT NOT NULL,​
sale_date DATE NOT NULL,​
customer_id INT NOT NULL,​
amount DECIMAL(10,2) NOT NULL​
)​
PARTITION BY RANGE (YEAR(sale_date)) (​
PARTITION p2020 VALUES LESS THAN (2021),​
PARTITION p2021 VALUES LESS THAN (2022),​
PARTITION p2022 VALUES LESS THAN (2023),​
PARTITION p2023 VALUES LESS THAN (2024)​
);​
​
允许。跳过 GIPK 创建。​
​
​
binlog_format=statement 下​
执行 Create table select​
​
set binlog_format=statement;​
create table gipk_test as select * from t_gipk;​
​
不允许。无法修改为 SBR。​
​
​
​
ALTER TABLE​
示例中使用的表结构​
  • GIPK 表: create table gipk_test(i int, c varchar(255));​
  • 普通主键表:create table gipk_test(i int auto_increment primary key, c varchar(255));​
​
描述​
DDL 示例​
MySQL 5.7​
MySQL 8.0​
MySQL 8.4​
给 GIPK 主键表添加主键​
​
alter table gipk_test add column id int primary key;​
​
允许。​
​
​
给无主键表添加了自增列​
​
alter table gipk_test add column id int auto_increment;​
​
不允许。​
ERROR 1075 AUTO INC 必须为索引,原生行为。​
​
​
给无主键表添加了自增列并作为 KEY​
​
alter table gipk_test add column id int auto_increment key;​
​
允许。​
​
​
用户给无主键表添加了自增列并作为 UNIQUE KEY​
​
alter table gipk_test add column id int auto_increment unique key;​
​
允许。​
​
​
Drop 表中的隐藏主键列​
​
alter table gipk_test drop column `my_row_id`;​
​
允许。​
​
​
Drop 表中的主键列​
​
create table gipk_test(i int primary key, c varchar(255));​
alter table gipk_test drop column i;​
​
允许。​
变为无主键表。​
​
​
Drop 表中的主键​
​
create table gipk_test(i int primary key, c varchar(255));​
alter table gipk_test drop primary key;​
​
允许。​
变为无主键表。​
​
​
Drop 表中的隐藏主键​
​
alter table gipk_test drop key `my_row_id`;​
​
允许。​
​
​
将表中的一列升级为主键​
​
create table gipk_test(f1 int , f2 int , f3 varchar(16) , c varchar(255));​
​
alter table gipk_test add primary key (f1);​
​
允许。​
​
​
GIPK 表将 GIPK 作为分区键​
​
CREATE TABLE gipk_test (f1 INT);​
ALTER TABLE gipk_test PARTITION BY KEY(byte_rds_ai_uk_row_id) PARTITIONS 10;​
​
不允许。​
隐藏列不应作为分区键,DDL 报错。​
​
​
GIPK 表将其他列作为分区键​
​
CREATE TABLE gipk_test (f1 INT);​
ALTER TABLE gipk_test PARTITION BY KEY(f1) PARTITIONS 10;​
​
允许。​
同时 DROP GIPK 列。​
​
​
​
告警处理​
关于隐藏主键相关的告警处理,请参见如何处理隐藏主键相关报错。​
​
最近更新时间:2026.10.09 18:07:11
这个页面对您有帮助吗?
有用
有用
无用
无用