mysql隐藏列rowid
显式rowid:(可以被查询到)
1 、当表中有 主键 并且是 数值型 的时候才是显示的
2、当表中没有主键的时候,但是表中有 唯一非空 并且是 数值型 的时候才是显示的
mysql> show create table t1;
CREATE TABLE `t1` (
`id` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='disttype=normal'
mysql> select *,_rowid from t1;
+----+--------+
| id | _rowid |
+----+--------+
| 1 | 1 |
| 2 | 2 |
+----+--------+
2 rows in set (0.00 sec
删掉:
alter table test.t1 drop primary key;
再查:
select *,_rowid from t1;
报错!!
=====================================
隐式rowid:(不可被查询)
表中不存在上述二种情况的时候,mysqI底层会给你创建一个6字节大小的指针,最大为2^48次幂,达到最大值之后rowid会从0开始。
当表中数据条数达到2^48后,此时再插入三条数据,此时a1 a2被覆盖了,所以在不满足上述二种情况(主键,非空唯一索引)的时候,
生成的隐式rowid在用尽之后,之前的记录会被覆盖,所以创建表一定要有主键id,避免发生覆盖,虽然概率比较低,这个只是用主键的其中一个原因。
实验:
在开始动手前,还需要做一点铺垫, 在 innoDB 中其实维护了一个全局变量 dictsys.row_id ,没有定义主键的表都会共享使用这个 row_id ,
在插入数据时会把这个全局 row_id 当作自己的主键,然后再将这个全局变量加 1。
gdb调试:
gdb 是一个在Linux下的调试工具,可以用来调试可执行文件。在服务器上,先通过 yum install gdb 安装,
安装完成后,通过下面的 gdb 命令 把 row_id 修改为 1:
ps -ef|grep muysql
gdb -p 2068 -ex 'p dict_sys->row_id=1' -batch
表中插入数据:
改row_id为最大:
gdb -p 2068 -ex 'p dict_sys->row_id=281474976710656' -batch
再插入数据,发现前面数据被覆盖了。
所以当表中的主键或唯一索引不满足我们前面提到的要求时, innoDB 使用的隐式的 _rowid 是存在一定风险的,虽然说 2^48 这个值很大,但还是有可能被用尽的,
当 _rowid 用尽后,之前的记录就会被覆盖。从这一角度也可以提醒大家,在建表时一定要创建主键,否则就有可能发生数据的覆盖。