2009-09-05 25 views
1

定的邏輯資源標識符(每行一個)的表,什麼是數據庫客戶端任意數量的執行以下操作的最佳方式:使用SQL Server作爲資源鎖定機制

  • 索賠訪問特定的資源,如果它尚未權利
  • 選擇下一個可用的資源和權利要求它(類似於上文)
  • 釋放先前權利資源

(該表將有一個「索賠人」列,這將是無人認領的行NULL)。

我卡在這些操作的原子性:我需要一個全表鎖之前,我選擇請求/下一個可用資源(並在事後更新,假設索賠成功),還是有更詳細的方式來做到這一點?我現在沒有大量的數據,但是我希望儘可能保持表格的可訪問性。

回答

3

您基本上描述了一個基於經典隊列的工作流程,您應該考慮使用真實的queue

爲了討論方便,這裏是你如何實現你的願望:

  • 要求特定的資源:SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK) WHERE key = @key。將阻止資源是否已被聲明。如果資源已經聲明,則使用鎖定超時來返回異常。 key必須被索引和唯一。
  • 下一可用資源:SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK, READPAST) ORDER BY <accessorder>。您必須通過表示資源偏好(最早,最高優先等)來定義訂單。
  • 發佈聲明資源:COMMIT您的交易。

問題的要點是使用正確的鎖提示,這種問題確實需要顯式鎖提示來解決。 UPDLOCK將充當'索賠'鎖。 ROWLOCK創建正確的粒度,防止服務器「優化」到頁面鎖定。 READPAST允許您跳過聲明的資源。在行上放置UPDLOCK將鎖定該行並允許您稍後更新它,但會阻止其他操作,如阻止鎖定行的普通讀取提交SELECT。這個想法是,儘管如此,無論如何,你將要更新行,這將放置一個不可避免的X鎖。如果您想保持表格更多可用,您可以使用app locks來代替,但是要正確拉出很困難。您將需要在資源的字符串描述符上請求應用程序鎖,例如密鑰值或密鑰的CHECKSUM或它的%%LOCKRES%%值。應用程序鎖允許您通過在「會話」作用域請求應用程序鎖來將「聲明」的範圍與事務分開,但必須手動發佈聲明(「提交時釋放」事務「作用域應用程序鎖定) 。但是,請注意,有一千種方法可以通過應用程序鎖定在腳下拍攝自己。

+0

感謝您的回答。隊列不合適,因爲這些實質上是永久性資源。另外,我應該澄清一下,客戶會要求任意時間的資源(包含多個SQL會話);這就是索賠人列的出處。但聽起來像是一個事務+ UPDLOCK/ROWLOCK,我可以檢查索賠人列是否爲非NULL,寫入並提交。 – 2009-09-05 19:23:25

+1

隊列不需要存儲資源,但是事件通知工作流需要處理的資源可用性。處理程序選取隊列消息(即「事件」),並且它們對資源執行操作。完成後,將新事件放置在隊列中,表示該資源可用於工作流程的下一階段。或者他們在隊列中放置一個計時器(http://msdn.microsoft.com/zh-cn/library/ms187804.aspx)以在特定時間後恢復該特定資源上的工作流。 – 2009-09-05 19:30:25

+1

在我的情況下,聲明持續聲明過程的生命週期 - 我正在使用它來拆分多個服務器之間的數據層次結構。但這聽起來像我應該閱讀有關隊列。謝謝你的幫助。 – 2009-09-05 19:33:31

3

SQL Server有一個名爲sp_getapplock的內置存儲過程。該文檔將其描述爲:

對應用程序資源進行鎖定。

客戶端可以競爭指定的鎖(您給它一個你想要的名字),一旦鎖被鎖定,執行所需的操作。客戶端崩潰,鎖自動釋放。要以編程方式解除鎖定,您可以使用applocks

  • 如果申請人是空調用sp_releaseapplock

    一個更多鈔票的解決方案,嘗試如果獲得的AppLock搶名稱相同

  • 的的AppLock,更新與您的claiment id行。
  • 一旦該行聲稱,釋放的AppLock因爲沒有其他客戶端將嘗試並聲稱,現在它已經聲稱
  • 完成後,更新claiment爲null
+1

由於這些是基於行的資源,我不能使用這種機制 - 但很高興知道。 – 2009-09-05 19:27:07

+1

添加了一個示例解決方案,以概述在這種情況下如何使用applocks – 2009-09-05 19:35:52