我知道SQL語句默認情況下不會異步執行,但我有一種似乎表現得那樣的情況。SQL Server似乎以異步方式運行
表
[#data]
[tbl_Bucket]
[tbl_IDPool]
程序
[sp_InsertIntoBucket]
[sp_GenerateID]
[sp_UpdateIDPool]
過程
- 應用程序調用
[sp_InsertIntoBucket]
[sp_InsertIntoBucket]
呼叫[sp_GenerateID]
[sp_GenerateID]
查詢[tbl_IDPool]
併產生一值[sp_GenerateID]
呼叫[sp_UpdateIDPool]
[sp_UpdateIDPool]
寫入[tbl_IDPool]
[sp_GenerateID]
返回其生成的值到[sp_InsertIntoBucket]
[sp_InsertIntoBucket]
使用該值作爲[tbl_Bucket]
爲一個新的記錄的主鍵
[sp_InsertIntoBucket]
將生成的值返回給調用者
方案
[#data]
有資料 - 往[tbl_Bucket]
(1500個12000記錄)。由於[sp_InsertIntoBucket]
一次只能處理一個記錄,因此該過程被RBAR化 - 對於[#data]
[sp_InsertIntoBucket]
中的每個記錄被調用。
問題
[sp_GenerateID]
產生重複的值。在發生[sp_InsertIntoBucket]
的實際INSERT
併發生錯誤之前,我有13到130個重複生成的值。
所生成的值是依賴於在[tbl_IDPool]
數據,因此同樣重要的是[sp_UpdateIDPool]
被調用用於每個[sp_GenerateID]
呼叫,以確保下一[sp_GenerateID]
呼叫生成一個唯一的值。
我懷疑它與[sp_GenerateID]
被調用[sp_UpdateIDPool]
可以完成寫入[tbl_IDPool]
之前被調用。但是這沒有意義,因爲RBAR應該等待[sp_InsertIntoBucket]
,它應該等待[sp_GenerateID]
,它應該等待[sp_UpdateIDPool]
,然後才能轉到下一個[#data]
條目,對吧?
我已經試過
WAITFOR DELAY "00:00:00.003"
- 這工作,但我正在尋找一個更好,更高效,更優雅的解決方案。WHILE
與CURSOR
- 唯一的區別是CURSOR
稍微慢一些。- 有和沒有
WITH (NOLOCK)
在[sp_GenerateID]
查詢[tbl_IDPool]
希望寫入(第一次調用)會鎖定讀取(第二次調用)。
您應該避免在存儲過程名稱的開頭使用'sp_'。在文檔中有關於爲Microsoft * system *過程保留的警告,如果名稱發生衝突(現在或稍後更新系統),Microsoft會「贏」。 – 2014-10-02 09:49:08
@Damien_The_Unbeliever這很有趣。感謝您的提醒。我沒有意識到這一點,將來會這樣做 - 或者我應該說*不*這樣做。然而,在這種情況下,僅僅是區分實體類型。您的警告已被記錄。 – that0th3rGuy 2014-10-02 10:00:48
你在不同的事務之間有併發,對吧?你爲什麼認爲交易內部存在異步?競爭條件似乎很好地解釋了這種行爲。 – usr 2014-10-02 10:22:50