2011-03-16 141 views
6

難道不知怎的,MySQL會生成兩次相同的自動增量ID嗎?MySQL重複ID

我們有以下的情況:

  1. ID爲法案= 100創建;

  2. 然後它被刪除;

  3. 然後創建另一個賬單並且它具有相同的id = 100;

表的結構是:

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?

更新:我們不能再現這種情況,但我們記錄了它。

+0

你的意思是你登錄了嗎?它是否表明這實際上發生了?你能告訴我們嗎? – 2011-03-16 07:22:50

+0

帳單創建完成後,還會在具有相同ID的外部付款系統中創建另一個帳單,並且該系統顯示有兩張帳單有重複的ID。 – 2011-03-16 07:40:46

+0

賬單的ID是否也從支付系統插入到數據庫中?因爲MySQL不應在自動增量字段上生成重複ID - 即使某些ID已被刪除(除非您截斷表)。 – BigFatBaby 2011-03-16 08:33:22

回答

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) 
+0

你太棒了!謝謝! – 2011-03-16 15:22:39

0

也許刪除是在事務提交之前完成的?我想在這種情況下,記錄永遠不會實際更新內部計數器。這只是一個猜測,但你可以嘗試通過在SQL腳本中插入,選擇和刪除語句來重現它,並圍繞每對插入,選擇和刪除事務?

+0

問題是第一次插入,刪除和第二次插入都是在他們自己的短交易中執行的。 – 2011-03-16 07:38:37