2011-12-07 21 views
2

內部應用程序需要根據某些提供的條件動態創建SQL表。這個應用程序有多個使用者。SQL Server - 確保只有一個事務嘗試創建表

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'SomeTableName')) 
BEGIN 
    -- Create table in here. 
END 

要做到這一點,我有上述基本構造內的存儲過程。我意識到可能的競爭條件,所以我的第一個解決方案是向SELECT語句添加一些鎖定提示,以確保檢查表存在的所有其他事務將被阻塞,直到其他事務完成。但是,無論我使用哪種提示,這都行不通。

我的下一個解決方案是將表創建封裝在TRY..CATCH中,以便即使它失敗了,我也可以忽略該錯誤。但是,CREATE TABLE語句的失敗會導致事務失敗,所以即使我忽略了錯誤,我也無法繼續。

我的最後一個解決方案是使用TRY..CATCH構造,如果出現錯誤,那麼GOTO創建新事務的存儲過程的頂部GOTO,一切順利,因爲表存在第二次回合。

我對解決方案不滿意,因爲它看起來像一個黑客。任何知道這個問題的乾淨解決方案的SQL專家?

爲了澄清一下,我上面討論的解決方案對性能沒有太大的影響,所以我真的在尋找一個沒有太大性能影響的乾淨解決方案。

回答

2

使用帶有sp_getapplock(代碼頂部)和sp_releaseapplock(代碼底部)的信號量(也稱爲手動鎖定)來確保只有一個進程。

一個第二進程將失敗或等待或根據您的sp_getapplock參數

+0

好超時,這是另一種可能的解決辦法,但我假定這將意味着該存儲過程的所有接聽的話會有連續的,會導致性能問題? – user1085351

+1

@ user1085351:正確,但是您的代碼無論如何都不是併發安全的,並且您使用重試。更糟糕的是?重試還是等待? – gbn

+0

好吧,爲什麼它不是安全的?如果重試意味着性能不會受到太大影響,則等待更糟糕。 – user1085351