InnoDB的”auto_increment”指定值被重置问题

日期: 2010-04-07 作者:minglog 来源:TechTarget中国 英文

  有时候新建的表需要对自增列指定初始值,但是有时候会出现明明指定过的初始值却被重置的现象。下面以一个小实验来说明这个问题:

  MySQL version:5.1.42 OS:redhat5.3

  无废话,建张表先:

  CREATE TABLE `sbtest1` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `k` int(10) unsigned NOT NULL DEFAULT ‘0’,
  `c` char(120) NOT NULL DEFAULT ”,
  `pad` char(60) NOT NULL DEFAULT ”,
  PRIMARY KEY (`id`),
  KEY `k` (`k`)
  ) ENGINE=InnoDB AUTO_INCREMENT=20000000 DEFAULT CHARSET=latin1;

  诸位看官可以看见我指定了auto_increment=20000000。

  表建好后,如果紧接着插数据,那么此现象是不会出现的:

  mysql> insert into sbtest1(k,pad) values(123,’what are you doing’);
  Query OK, 1 row affected (0.00 sec)
  mysql> select * from sbtest1;
  +———-+—–+—+——————–+
  | id | k | c | pad |
  +———-+—–+—+——————–+
  | 20000000 | 123 | | what are you doing |
  +———-+—–+—+——————–+
  1 row in set (0.00 sec)

  那什么时候?嗯,确切地说是做什么样的操作,重置现象才会出现呢?看实验:

  CREATE TABLE `sbtest1` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `k` int(10) unsigned NOT NULL DEFAULT ‘0’,
  `c` char(120) NOT NULL DEFAULT ”,
  `pad` char(60) NOT NULL DEFAULT ”,
  PRIMARY KEY (`id`),
  KEY `k` (`k`)
  ) ENGINE=InnoDB AUTO_INCREMENT=20000000 DEFAULT CHARSET=latin1
  mysql> quit
  Bye
  [root@test_2 ~]# service mysqld restart
  mysql> show create table sbtest1 G
  *************************** 1. row ***************************
  Table: sbtest1
  Create Table: CREATE TABLE `sbtest1` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `k` int(10) unsigned NOT NULL DEFAULT ‘0’,
  `c` char(120) NOT NULL DEFAULT ”,
  `pad` char(60) NOT NULL DEFAULT ”,
  PRIMARY KEY (`id`),
  KEY `k` (`k`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1
  1 row in set (0.00 sec)

  这时,auto_increment的值被重置了!

  通过以上的小实验,结合手册就能理解为什么会发生这种现象了:

  如果对某张innodb表指定了auto_increment,那么innodb就会在data dictionary为它维护一个auto_increment计数器,注意:这个计数器只存储在内存中,不会写在disk上。

  那么 innodb在DB重启后,如何对这个计数器进行初始化呢(结合实验中的这张表来说明?

  InnoDB在数据库重新启动后,它会对指定过 auto_increment的表(sbtest1)做这样一个操作:

  SELECT MAX(id) FROM sbtest1 FOR UPDATE;

  然后将这条语句取得的值+1赋给被指定auto_increment的字段和在内存中的这张表的计数器。如果表是空的,那么这个值将会是1.

  解决方法:

  1.重建完表后,插入数据之前不要重启(说白了,就是要保证内存的数据不会释放)

  2.插入一条脏数据

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

作者

minglog
minglog

相关推荐

  • MariaDB InnoDB表空间碎片整理

    从MariaDB 10.1开始,MariaDB把Facebook的碎片整理代码合并进来了,并且把所有代码都调整到InnoDB/XtraDB层去实现,因而只需要使用现成的 OPTIMIZE TABLE 命令就行。

  • 甲骨文宣布MySQL Cluster 7.4全面上市

    甲骨文公司今天宣布MySQL Cluster 7.4全面上市。MySQL Cluster是一款ACID兼容的开源事务处理型数据库,具有实时内存性能和99.999%的可用性。

  • 不同事务隔离级别对MySQL性能的影响

    在这篇文章里,我们将讨论InnoDB 事务隔离模式,还有它们与MVCC(多版本并发控制)的关系,以及它们是如何影响MySQL性能的。

  • 解读MySQL数据库的双向复制

    在主-从复制中,主机影响从机。但从数据库中的任何更改不会影响主数据库,这篇文章将帮助你实现双向复制。