我正在處理一個大型的SQL Server數據庫,這是建立在主鍵值的計數器表的基礎上的。每個表在此計數器表中都有一行,其中包含PK名稱和下一個要用作主鍵(用於該表)的值。我們目前得到的計數值的方法是這樣的:SQL Server中「計數器」表的最佳實現
BEGIN TRAN
UPDATE CounterValue + 1
SELECT Counter Value
COMMIT TRAN
這作品大多很好,因爲在開始交易,然後更新該行的過程中,鎖定行/頁/表(鎖定ISN水平對於這個話題來說太重要了),直到交易被提交。
這裏的問題是,如果事務長時間保持打開狀態,訪問該表/頁/行的時間太長。我們有在單個事務中可能出現數百個插入的情況(需要訪問此計數器表)。
解決此問題的一個嘗試是始終使用應用程序中不會保持事務處於打開狀態的單獨連接。訪問表和事務處理會很快,所以訪問表通常是可用的。這裏的問題是,使用觸發器可能也需要訪問這些計數器值,這是一個相當不合理的規則。換句話說,我們有觸發器也需要計數器值,而這些觸發器有時在較大的父事務處理的上下文中運行。
解決此問題的另一個嘗試是使用SQL Server應用程序鎖來序列化對錶/行的訪問。大多數情況下也是如此,但有缺點。這裏最大的缺點之一還涉及觸發器。由於觸發器在觸發查詢的上下文中運行,應用程序鎖將被鎖定,直到任何父事務完成。
因此,我試圖找出一種方法來序列化訪問行/表可以從應用程序或SP /觸發器,永遠不會運行在父事務的上下文中運行。如果父母交易回滾,我不需要計數器值回滾。總是可用的情況下,如果父事務處理回滾,則快速訪問計數器值比丟失一些計數器值要重要得多。
我應該指出,我完全意識到使用GUID值或標識列可以解決我的很多問題,但正如我所提到的,我們正在討論一個龐大的系統,其中包含大量的數據,在合理的時間範圍內改變,而不會給我們的客戶帶來很大的痛苦(我們正在談論成百上千萬行的數百張表)。
有關實現這種櫃檯表的最佳方法的任何想法,將不勝感激。請記住 - 訪問應始終可用於許多應用程序,服務,觸發器和其他SP,並且阻塞很少。
編輯 - 我們可以假設的SQL Server 2005+
您正在使用什麼版本的SQL Server? –
SQL Server 2012最終支持序列。我非常肯定,那些在引擎之外構建的任何東西都更加健壯和快速。因此,如果您不在SQL Server 2012上,升級可能比實施和維護本土解決方案更便宜。 –
您仍然可以使用標識列而不更改其他表格。就像'CREATE TABLE counter(counter INT IDENTITY(1,1)PRIMARY KEY);',然後'INSERT INTO counter DEFAULT VALUES; SELECT @@ SCOPE_IDENTITY; DELETE FROM counter WHERE counter = @@ SCOPE_IDENTITY;',也許? – hvd