自增键用完了会发生什么?
我们在建表的时候为某个索引列( 注意:必须是索引列 )添加 AUTO_INCREMENT
属性,就像这样:
CREATE TABLE t ( c1 TINYINT AUTO_INCREMENT, c2 TINYINT, KEY idx_c1 (c1) ) ENGINE=InnoDB;
表 t
中包含一个索引列 c1
,该列被添加了 AUTO_INCREMENT
属性。我们先向该表中插入一条记录:
mysql> INSERT INTO t(c1, c2) VALUES(126, 1); Query OK, 1 row affected (0.02 sec)
之后我们不再在 INSERT
语句中显式地插入 c1
列的值,它的默认值就将是从当前插入的最大的那个值之后自增,比如这样:
mysql> INSERT INTO t(c2) VALUES(1); Query OK, 1 row affected (0.01 sec)
我们看一下此时表 t
中的数据:
mysql> SELECT * FROM t; +-----+------+ | c1 | c2 | +-----+------+ | 126 | 1 | | 127 | 1 | +-----+------+ 2 rows in set (0.02 sec)
因为 c1
列是 TINYINT
类型的,使用1个字节存储数据,它能存储最大的值就是 127
,如果当该列的值到达 127
之后,我们继续向表中插入数据,自增列 c1
的值将会变成什么呢?
mysql> INSERT INTO t(c2) VALUES(1); Query OK, 1 row affected (0.01 sec)
插入成功之后我们再看一下表中的数据:
mysql> SELECT * FROM t; +-----+------+ | c1 | c2 | +-----+------+ | 126 | 1 | | 127 | 1 | | 127 | 1 | +-----+------+ 3 rows in set (0.01 sec)
很显然,自增列 c1
的值将不再继续增长,而是取的 TINYINT
所能存储的最大值。
这里需要注意的是,在当前举的例子中,我们只是在自增列 c1
上边建立了一个普通的二级索引 idx_c1
,所以键值重复也没啥问题。不过我们一般将 AUTO_INCREMENT
属性应用在表的主键上,此时如果自增列值达到了主键对应数据类型所能存储的最大值时,就会报错(因为主键值重复),大家一定注意!
row_id用完了会发生什么?
在我们使用 InnoDB
存储引擎来建表时,如果我们自己没有显式地创建主键时,存储引擎会默认找一个具有 NOT NULL
属性的唯一二级索引列来充当主键,如果我们在建表语句中也没有写具有 NOT NULL
属性的唯一二级索引列,那很抱歉,存储引擎默认会为我们添加一个称之为 row_id
的主键列。
这个 row_id
列默认是6个字节大小,值得注意的是,设计 InnoDB
的大叔并不是为每一个用户未显式创建主键的表的 row_id
列都单独维护一个计数器,而是所有的表都共享一个全局的计数器。比方说我们没有对表 t1
和 t2
显式创建主键,存储引擎为它们都创建了一个 row_id
列,如果我们向表 t1
中插入了一条记录,那么就从全局计数器里分配一个值做该表 row_id
列的值,然后将全局计数器加1;接着我们再向表 t2
中插入一条记录,那么就再从全局计数器里分配一个值做该表 row_id
列的值,然后将全局计数器加1。
有很多同学有疑惑,如果这个全局计数器的值超过了6个字节所能表示的最大值时,会发生什么,全局计数器从0重新开始技术,一切从头再来么?
哈哈:smile:,并不会这样。虽然 row_id
由6个字节组成,但是设计 InnoDB
的大叔却是使用8个字节存储全局计数器的值,他们将这8个字节分两次写入 row_id
,第一次写入右边四个字节到 row_id
的右边4个字节,接着将左边四个字节再写入 row_id
的左边的2个字节,就像这样:
在将全局计数器左边四个字节再写入 row_id
的左边的2个字节 时采用如下函数:
UNIV_INLINE void mach_write_to_2( /*============*/ byte* b, /*!< in: pointer to two bytes where to store 也就是row_id值前2个字节所在的内存地址*/ ulint n) /*!< in: ulint integer to be stored 也就是全局计数器的左4个字节值*/ { ut_ad(b); ut_ad((n | 0xFFFFUL) <= 0xFFFFUL); b[0] = (byte)(n >> 8); b[1] = (byte)(n); }
可以看到代码中有这样一行:
ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);
这是一个断言函数,这行代码的意思就是全局计数器的左边4个字节值 n
必须不大于2个字节所能存储的最大值,否则的话断言就失败了,然后 MySQL 就挂掉了,就挂掉了,就挂掉了~
也就是说如果 row_id
用完了之后MySQL就会挂掉,那种程序直接退出的挂掉~ 不过6个字节已经足够大了,大家可以算算如果想让MySQL挂掉需要插入多少条记录呢?
小青蛙历史文章(历史文章,不容错过):
MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!
长按关注小青蛙,都是干货喔
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据挖掘导论
Pang-Ning Tan, Michael Steinbach / 范明 范宏建 / 人民邮电出版社 / 2006-01-01 / 49.00元
本书全面介绍了数据挖掘的理论和方法,旨在为读者提供将数据挖掘应用于实际问题所必需的知识。本书涵盖五个主题:数据、分类、关联分析、聚类和异常检测。除异常检测外,每个主题都包含两章:前面一章讲述基本概念、代表性算法和评估技术,后面一章较深入地讨论高级概念和算法。目的是使读者在透彻地理解数据挖掘基础的同时,还能了解更多重要的高级主题。此外,书中还提供了大量示例、图表和习题。 本书适合作为......一起来看看 《数据挖掘导论》 这本书的介绍吧!