2012-01-24 71 views
3

我很熟悉InnoDB中插入失敗導致自動遞增主鍵存在差距的事實,我認爲這是不相關的(這對我來說並不明顯)。我遇到的問題是我將5個記錄插入一個帶有自動遞增主鍵的表格中,這會導致主鍵的間隔從5到8.下面是一個重複該問題的腳本。爲什麼INNODB批量插入會導致自動遞增主鍵跳過值?

DROP TABLE IF EXISTS `test_table`; 
CREATE TABLE `test_table` (
`A` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`B` int(10) unsigned NOT NULL, 
PRIMARY KEY (`A`) 
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

insert into `test_table` (`B`) 
SELECT 1 
UNION 
SELECT 2 
UNION 
SELECT 3 
UNION 
SELECT 4 
UNION 
SELECT 5; 

insert into `test_table` (`B`) 
SELECT 6 
UNION 
SELECT 7 
UNION 
SELECT 8 
UNION 
SELECT 9 
UNION 
SELECT 10; 

SELECT * FROM `test_table`; 

我希望兩列A和B是在這種情況下是相同的,但在第二插件A的開始將是8,和B將是6有誰知道爲什麼這個差距會發生?

我看過這裏的文檔:http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html但這些鎖定模式似乎並沒有與這種差距有關(我可能會錯過某些東西)。

回答

1

我認爲查詢分析器被要求粗略估計內部查詢將返回多少行,並且它稍微關閉。

數據庫引擎需要努力了三個相互矛盾的目標:

  • 交易必須是原子,所以在交易中從序列產生的任何號碼必須是連續的。
  • 序列不應被鎖定的時間(否則,其他INSERT操作將被阻止),
  • 內部查詢應該不需要實現完整的結果表,其可以是相當的延伸量大。

由於沒有人保證序列號在全局上是連續的,所以最好的方法是獲得必須插入的行數的上限,然後按照該量增加序列(原子地)並使用塊因此爲INSERT操作保留。

這可以確保併發INSERT將具有較小或較大的主鍵值(即查詢已正確序列化),但可以在行之間添加數據(因爲沒有排序,除非使用ORDER BY子句)

4

出於某種原因 'INSERT INTO test_tableB)選擇1 UNION SELECT 2' 設置AUTO_INCREMENT = 4,但此插入按預期工作 -

INSERT INTO `test_table` (`B`) 
VALUES (1), (2), (3), (4), (5); 

INSERT INTO `test_table` (`B`) 
VALUES (6), (7), (8), (9), (10); 

嘗試設置innodb_autoinc_lock_mode = 0和運行你的腳本再次,不會有空白。

AUTO_INCREMENT Handling in InnoDB