2009-09-09 33 views
8

今天我遇到了一些好奇的行爲,並想知道它是預期的還是標準的。我們對MySQL5使用Hibernate。在編碼過程中,我忘記關閉交易,我想其他人可以聯繫。未提交的數據庫事務和自動增加列

當我最後關閉事務時,運行代碼並檢查了表,我注意到以下內容。所有時間我錯誤地運行我的代碼而沒有關閉事務,因此沒有導致實際的行被插入,但增加了自動增量代理主鍵值,這樣我就有一個間隙(即沒有行的id字段值爲751至762)。

這是預期的還是標準的行爲?可能會因數據庫而異?和/或Hibernate自己的事務抽象對此有一些可能的影響嗎?

+0

我知道答案,但這仍然是一個有趣的問題! – RichardOD 2009-09-09 14:22:48

+1

理想情況下,您的應用程序/設計不應受序列中任何空白的影響 - 您絕不應該陷入這種情況下 – 2009-09-09 15:28:24

回答

8

是的,這是預期的。

如果你想一想:數據庫還能做什麼?如果增加列,然後在同一事務中的其他插入中將其用作外鍵,並且在您這樣做時,其他人提交,那麼他們將無法使用您的值。你會得到一個差距。

像Oracle這樣的數據庫中的序列的工作方式大致相同。一旦請求了特定的值,它是否被提交併不重要。它永遠不會被重用。序列也不是絕對有序的。

6

這是非常期待的行爲。如果沒有,數據庫將不得不等待每個已經插入記錄的事務完成,然後將新的ID分配給下一個插入。

5

是的,這是預期的行爲。 This documentation解釋得非常好。

從5.1.22開始,實際上有三種不同的鎖定模式來控制併發事務如何獲得自動增量值。但是這三者都會導致回滾事務的空隙(回滾事務所使用的自動增量值將被丟棄)。

0

數據庫序列不保證沒有間隙的id序列。它們被設計成獨立於事務,只有在這種方式下才可以是非阻塞的。

你想要沒有差距,你必須編寫自己的存儲過程來事務性地增加列,但是這樣的代碼會阻塞其他事務,所以你必須是carrefull。

你做SELECT CURRVAL FROM SEQUENCE_TABLE WHERE TYPE =:YOUR_SEQ_NAME FOR UPDATE; UPDATE SEQUENCE_TABLE SET CURRVAL =:INCREMENTED_CURRVAL WHERE TYPE =:YOUR_SEQ。