2010-09-09 35 views
3

我有一個MySql表與自動增量主鍵,似乎所有的各種upsert方法(INSERT IGNORE和ON DUPLICATE KEY UPDATE)遭受,呃,即使一個行被更新並且沒有被插入,自動遞增字段也會增加。這意味着在表格中引入了差距,我認爲這是不理想的。MySql的upsert和自動增量導致空白

所以問題是:如果upsert實際上只是更新行,是否有任何方法可以自動遞增該字段,以自動遞增字段而不是來插入表中的記錄。在我看來,這是upsert應該表現的方式,但似乎並非如此。

+1

我覺得你對這些差距的擔憂是一種更不可取的方式。一個人完全不關心auto_oncrement數字。你可能誤解了它的概念。 – 2010-09-09 18:55:12

+1

我知道實際值是毫無意義的,但如果浪費太多空間,則可能會用盡空間並需要更大的數據類型,然後所有行將佔用更多的空間。此外,我發現這些差距不夠優雅,但我認爲這不是最大的交易。 – 2010-09-09 19:32:43

+0

MySQL支持'SERIAL'類型,它是'BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE'的別名。 'BIGINT'可以保存值高達'18,446,744,073,709,551,615'。我留下了一個很好的比喻(比如宇宙時代等),作爲讀者的練習。而且它也只有8字節。 – Quassnoi 2010-09-09 19:53:57

回答

4

這個「問題」只在InnoDB

它是通過設計,旨在提高併發性:另一個線程可以使用AUTO_INCREMENT而不必等待UPSERT操作的結果。

docs

服務器啓動後,第一個插入表tInnoDB執行該語句相當於:

SELECT MAX(ai_col) FROM t FOR UPDATE; 

...

InnoDB初始化但不增加值並將其存儲f或通過後插入

使用...

當訪問自動增長計數器,InnoDB採用了特殊的表級AUTO-INC鎖,它保持對當前SQL語句的結束,不是結束交易。引入了特殊的鎖定釋放策略來提高插入到包含AUTO_INCREMENT列的表中的併發性。儘管如此,兩個交易不能同時在同一張表上使用AUTO-INC鎖,如果AUTO-INC鎖持續很長時間,這會對性能產生影響。對於諸如INSERT INTO t1 ... SELECT ... FROM t2之類的陳述來說,情況可能如此,該陳述將一張表中的所有行插入另一張表中。

MyISAM不會出現這種行爲,因爲它是AUTO_INCREMENT算法的實現方式不同(由於其有限的支持併發DML能力)。

+0

感謝有關爲什麼這種行爲是按預期的詳細信息。我會接受答案,但我仍然想知道是否有任何高性能的方式來完成upsert沒有差距。 – 2010-09-09 19:35:22

+0

@Joshua:你可以創建一個單字段,單記錄「序列」表並在觸發器中更新它。但是,這會嚴重影響你的表的併發性。 – Quassnoi 2010-09-09 19:45:59

+0

@Quassnoi:我正在運行MyISAM並遇到同樣的問題 – hornetbzz 2011-03-18 22:21:56