2009-03-06 59 views
1

我有2個批處理程序,1是發送電子郵件和另一個發送傳真的程序。他們都訪問名爲QUEUE的表。在SQL Server中鎖定

在電子郵件發件人程序中,這與QUEUE有關。在QUEUE滿足標準的每個記錄:

  1. 鎖記錄1中QUEUE表:
    select 1 from QUEUE with (UPDLOCK) where id = 1
  2. 過程發送出電子郵件的
  3. 刪除記錄1 QUEUE表:
    delete from QUEUE where id = 1
  4. 犯交易(交易不是自動提交)

在傳真發件人程序中,除了在步驟2中發送傳真(當然)之外,也會發生類似的步驟。

問題是,有時從QUEUE刪除了一個異常,它被鎖定。從而重新發送電子郵件/傳真。我確信這些程序處理的記錄組不會相交。

似乎刪除嘗試獲取表中其他記錄上的更新(U)鎖,儘管只有一條記錄要刪除。因此,當其他事務鎖定在同一個表中的其他記錄時發生異常。

因此,我需要知道是否有一個選項可以使「刪除」操作不會獲取記錄以外的鎖,而是刪除它將刪除的記錄。因爲看起來問題在於「刪除」操作鎖定了表中的其他記錄。

順便說一句,這裏是有關數據庫的一些信息(我不知道他們是否會幫助):

  • 提交讀快照被打開
  • 快照隔離狀態是

回答

2

您是否嘗試過在刪除語句中使用WITH ROWLOCK或WITH NOLOCK提示?

你看過this article嗎?它建議你使用(UPDLOCK,READPAST),以防止遇到

0

有時,鎖會從鎖定單個行變爲鎖定表的一部分或鎖定整個表。這很可能是你爲什麼鎖定你在事務中沒有實際使用的記錄。

而不是使用事務來鎖定記錄,您可以使用狀態字段來標記處理的記錄。

例子:

鎖定一些記錄,然後獲取成功鎖定記錄:

update queue set status = 'email_processing' where status is null and id = 1 
select email, message from queue where status = 'email_processing' 

當你沒有明確地使用每個查詢在它自己的事務中運行一個事務,所以更新查詢可以安全地更改狀態,因爲它正在驗證同一查詢中的當前狀態。

完成後發送,刪除記錄:

delete from queue where status = 'email_processing' 

傳真發件人當然會用不同的狀態(如「fax_processing」),以便標記記錄被隔離。

+0

利用的建議,正是我所擔心的是,如果我遭遇期間,我刪除時間鎖定錯誤的問題你。即使我刪除了鎖,我仍然很容易在刪除期間遇到鎖定錯誤(它鎖定了其他記錄)。我在想的是在make部分嘗試刪除直到成功。 – rizza 2009-03-06 12:00:46

+0

是的,你可以做到這一點。但是,如果沒有交易,您不太可能會遇到鎖定問題。在運行下一個之前,數據庫通常會等待一個更新/刪除完成。大多數情況下,當您在事務處理過程中遇到冗長的進程或死鎖情況時,這是一個問題。 – Guffa 2009-03-06 12:39:59