2011-07-21 64 views
7

我正在使用DB2作爲其主數據庫的多線程應用程序。在過去,我們主要將Identity列用於需要自動生成的唯一標識符的表。要做到這一點,我們將運行在2個查詢在同一事務:如何在多線程應用程序中獲取DB2序列值

INSERT INTO tbname (IDENTITY_COL, ...) VALUES (DEFAULT, ...); 
SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1; 

我們現在正被迫改用序列代替。我知道你可以在INSERT和SELECT語句中使用「colname」的下一個值,但我無法弄清楚如何同時使用INSERT和SELECT,而不會冒險處理多線程應用程序中的爭用條件。例如,如果我使用:

INSERT INTO tbname (SEQUENCE_COL, ...) VALUES (NEXT VALUE FOR SEQUENCE_COL, ...); 
SELECT PREVIOUS VALUE FOR SEQUENCE_COL; 

還有一種可能性,另一INSERT,在前述INSERT和SELECT之間運行,因此我提供了不正確的值。如果我嘗試:

SELECT NEXT VALUE FOR SEQUENCE_COL; 

存儲在一個變量和值傳遞到INSERT:

INSERT INTO tbname (SEQUENCE_COL, ...) VALUES (variable_value, ...); 

還有一種可能性,另一個線程得到了相同的NEXT值,並試圖插入相同的值,導致DB2 -803錯誤。是否可以在多線程環境中使用SEQUENCE列,還是需要爭取保留我的IDENTITY列?

回答

6

除了邁克爾·Sharek(正確地)說:

INSERT INTO tbname (SEQUENCE_COL, ...) VALUES (NEXT VALUE FOR SEQUENCE_COL, ...); 
SELECT PREVIOUS VALUE FOR SEQUENCE_COL; 

你的假設然後還有另一個INSERT,在前述INSERT和SELECT之間運行的可能性,因此我提供關於不正確的值「上面的語句順序是不正確的。

「下一個值」和「以前的值」是連接特定的。

從不同線程訪問序列永遠不會創建「比賽」條件。每個連接都有一個完全隔離的序列「環境」。

+0

非常感謝您提供連接特定的說明。正是我需要聽到的。 –

6

你在你的問題中有一個錯誤的假設。

如果我嘗試:

SELECT NEXT VALUE FOR SEQUENCE_COL; 

存儲在一個變量和值傳遞到INSERT:

INSERT INTO tbname (SEQUENCE_COL, ...) VALUES (variable_value, ...); 

還有一種可能性另一個線程獲得了相同的下一個值並嘗試i插入相同的值

這是不正確的。第二個線程會得到不同的NEXTVAL,並且與第一個線程不同。

我還想加上這一部分我認爲:

我們現在正在被迫改用序列代替。

我無法想象有一個很好的理由從身份切換到序列。他們基本上是一樣的。

+0

感謝您的答覆。 a_horse_with_no_name提供的連接安全性的澄清使我更好地理解了爲什麼它沒問題,但這兩個答案都有很大的幫助。至於壓力,就是要減少Identities的一些開銷,並讓程序員更加關注如何設置這些列(高級解釋)。 –

2

除了其他的正確答案,你也可以只使用一個單獨的語句插入一行,並返回插入值如下:

SELECT SEQUENCE_COL FROM NEW TABLE (
    INSERT INTO tbname (SEQUENCE_COL, ...) VALUES (NEXT VALUE FOR MY_SEQUENCE, ...) 
)