MySQL重复ID

时间:2011-03-16 07:14:28

标签: mysql auto-increment

在某种程度上,MySQL会产生两次相同的自动增量ID吗?

我们有以下情况:

  1. 创建了id = 100的帐单;

  2. 然后它被删除;

  3. 然后创建另一个帐单,它具有相同的id = 100;

  4. 表的结构是:

    CREATE TABLE `bill` (
      `id` int(11) NOT NULL auto_increment,
      `user` int(11) NOT NULL,
      `date` datetime NOT NULL,
      `state` int(11) NOT NULL,
      `adv` bit(1) NOT NULL default b'0',
      `weight` int(11) default NULL,
      PRIMARY KEY  (`id`),
      KEY `FK2E2407EC768806` (`user`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
    
    ALTER TABLE `bill`
      ADD CONSTRAINT `FK2E2407EC768806` FOREIGN KEY (`user`) REFERENCES `user` (`id`);
    

    是否存在一些竞争条件或MySQL是否保证了独特的自动增量ID?

    更新:我们无法重现这种情况,但我们已将其记录下来。

2 个答案:

答案 0 :(得分:11)

不同的存储引擎以不同方式处理自动增量。例如,使用MyISAM时,下一个自动增量值将保持不变,这样如果重新启动MySQL服务器,它将保留该自动增量值。

但是,InnoDB不会保留下一个自动增量值,因此如果重新启动MySQL服务器,它将计算当前最大值并从那里开始增量。

这与您相关,因为您使用的是InnoDB。因此,如果100是表中的最大id值,则删除该行,然后重新启动MySQL服务器,然后在下一次插入时重新使用100。

这是一个简单的例子来说明这一点:

mysql> CREATE TABLE `bill` (
    ->   `id` int(11) NOT NULL auto_increment,
    ->   PRIMARY KEY  (`id`)
    -> ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.12 sec)

mysql> -- start at 99 to force next value to 100
mysql> insert into bill values (99);
Query OK, 1 row affected (0.01 sec)

mysql> -- use auto-increment, should be 100
mysql> insert into bill values (null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from bill;
+-----+
| id  |
+-----+
|  99 |
| 100 |
+-----+
2 rows in set (0.00 sec)

mysql> -- delete max value
mysql> delete from bill where id = 100;
Query OK, 1 row affected (0.00 sec)

mysql> -- use auto-increment, should be 101
mysql> insert into bill values (null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from bill;
+-----+
| id  |
+-----+
|  99 |
| 101 |
+-----+
2 rows in set (0.00 sec)

mysql> -- delete max value
mysql> delete from bill where id = 101;
Query OK, 1 row affected (0.00 sec)

mysql> 
mysql> /*** RESTART MYSQL ***/
mysql> 
mysql> -- use auto-increment, should be 100
mysql> insert into bill values (null);
Query OK, 1 row affected (0.01 sec)

mysql> select * from bill;
+-----+
| id  |
+-----+
|  99 |
| 100 |
+-----+
2 rows in set (0.00 sec)

答案 1 :(得分:0)

也许删除是在事务提交之前完成的?我想在那种情况下,记录永远不会真正更新内部计数器。这有点猜测,但您可以尝试通过在SQL脚本中插入,选择和删除语句并围绕每对插入,选择和删除事务来重现它吗?