MySQL中的隐式主键和隐藏列

从MySQL **8.0.30 **开始,MySQL支持为任何没有显式主键的InnoDB表生成不可见的主键。当sql_generate_invisible_primary_key服务器系统变量设置为ON时,MySQL服务器会自动将生成的不可见主键 GIPK 添加到任何此类表中。此设置对使用除InnoDB以外的任何其他存储引擎创建的表没有影响。

默认情况下,sql_generate_invisible_primary_key的值为OFF,这意味着GIPK的自动添加被禁用。

官方文档:https://dev.mysql.com/doc/refman/8.0/en/create-table-gipks.html

开源示例

MySQL 8.0.37

sql_generate_invisible_primary_key on

sql_generate_invisible_primary_key off

AliSQL

MySQL 8.0.36

sql_generate_invisible_primary_key off

AliSQL有自研的参数show_ipk_info用来控制是否显示隐式主键的信息

思考?

那么为什么再上述sql_generate_invisible_primary_key off的情况下依然会生成一个GEN_CLUST_INDEX聚集索引?

这是因为 InnoDB 存储引擎要求每个表必须有一个聚集索引。如果表中没有显式定义主键,也没有合适的唯一索引,InnoDB 会内部生成一个隐藏的聚集索引,通常命名为 GEN_CLUST_INDEX。

这个隐藏的聚集索引是构建在一个包含行 ID 值的合成列上的,即使没有生成隐藏列,这个索引也会被创建以满足 InnoDB 对聚集索引的要求。因此,关闭 sql_generate_invisible_primary_key 选项并不影响聚集索引的自动创建,它只影响是否生成一个不可见的主键列。

row_id 再MVCC中有过介绍

https://www.yuque.com/eucalyptus-byepv/epkbe4/bgohmgh5m2w69p0z

注意事项

当sql_generate_invisible_primary_key on时,创建的表有隐藏列 my_row_id 并且再该隐藏列上有primary key的情况下再去添加primary key是不被允许的

(1068, ‘Multiple primary key defined’)

并且删除隐藏列 my_row_id 和隐藏列 my_row_id 上的primary key都是不被允许的

(1235, This version of MySQL doesn’t yet support ‘existing primary key drop without adding a new primary key. In sql_generate_invisible_primary_key ON mode table should have a primary key. Please add a new primary key to be able to drop existing primary key.’ )