程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> 用TRY/CATCH解決sql server2005的死鎖

用TRY/CATCH解決sql server2005的死鎖

編輯:關於SqlServer

讓我們從這樣一個示例開始說起,它在 SQL Server 2000 和 2005 中都能引起死鎖。在本文中,我使用 SQL Server 2005 的最新 CTP(社區技術預覽,Community Technology Preview)版本,SQL Server 2005 Beta 2(7 月發布)也同樣適用。如果您沒有 Beta 2 或最新的 CTP 版本,請下載 SQL Server 2005 Express 的最新版本,用它來進行試驗。

可能發生的死鎖情況有很多,[參閱http://msdn.microsoft.com/library/default.asp?url=/library/en-us/acdata/ac_8_con_7a_3xrf.asp以及死鎖文章樹中的後續文章。— 編者 ],但最有趣、最微妙的是那些關於閱讀器和編寫器互相阻塞的死鎖。以下代碼在 pubs 數據庫中就產生了這樣一個死鎖。(您可以在 SQL Server 2000 的兩個 Query Analyzer 窗口中或 SQL Server 2005 的兩個 Management Studio queries 中並列運行這段代碼。)在其中一個窗口中的代碼正文前面添加下列語句:

-- Window 1 header
DECLARE @au_id varchar(11), @au_lname varchar(40)
SELECT @au_id = '111-11-1111', @au_lname = 'test1'

在第二個窗口中添加下列語句,進行第二次連接:

-- Window 2 header
DECLARE @au_id varchar(11), @au_lname varchar(40)
SELECT @au_id = '111-11-1112', @au_lname = 'test2'

在兩個窗口中都使用下列語句作為代碼正文:

-- Body for both connections:
BEGIN TRANSACTION
INSERT Authors VALUES 
  (@au_id, @au_lname, '', '', '', '', '', '11111', 0)
WAITFOR DELAY '00:00:05'
SELECT *
  FROM authors
  WHERE au_lname LIKE 'Test%'
COMMIT

在第三個窗口中運行下列語句,確保 authors 表格中沒有任何包含以下 id 的數據:

DELETE FROM authors WHERE au_id = '111-11-1111'
DELETE FROM authors WHERE au_id = '111-11-1112'

在 5 秒鐘內同時執行窗口 1 和 窗口 2。因為每個窗口都要等待至少 5 秒鐘的時間才能發出 SELECT 語句,所有每個連接都將完成 INSERT 操作,這樣就保證了兩個窗口中的 INSERT 操作在各自的 SELECT 語句發布前就已經完成了。每個窗口中的 SELECT 語句都嘗試讀取 authors 表格中的所有數據,查找 au_lname 字段值中類似“Test%”格式的數據。因此,兩個窗口中的 SELECT 語句都將嘗試讀取各自連接中的插入數據 — 也讀取對方連接中的插入數據。

read COMMITTED 隔離級別通過發布共享鎖確保 SELECT 語句永遠不讀取未提交的數據。對於同一個資源,共享鎖與排它鎖互不兼容,請求者在發布共享鎖之前必須等待排它鎖釋放。每個連接對於插入的數據都設置了排它鎖,因此嘗試讀取對方插入數據的 SELECT 語句將試圖解除插入數據的共享鎖,但它會被阻塞。兩個連接將互相阻塞,從而形成一個死鎖。SQL Server 的鎖定管理器檢測到死鎖時,將中止其中的一個批處理,回滾它的事務,釋放它的阻塞鎖,以便其他事務能夠完成。作為死鎖犧牲品的事務將回滾,其他事務則將成功完成。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved