close
文章出處

數據庫的讀讀事務也會產生死鎖

 

前段時間有朋友問:SQL Server的AlwaysOn的輔助數據庫默認會使用行版本快照控制來消除數據庫上的讀寫事務阻塞和死鎖問題

即使用戶顯式為查詢設置了其他事務隔離級別,所有鎖提示(Lock Hint)都會被忽略。

為了保證數據同步的完整性,AlwaysOn規定來自數據同步(redo 日志)所做的寫操作永遠不會被選為死鎖犧牲品,無論該寫操作的代價多小。

 

AlwaysOn的做法其實很好理解,數據庫中的事務操作無非就四種

1、讀讀 

2、讀寫

3、寫讀

4、寫寫

 

 

第二種、第三種和第四種造成阻塞和死鎖很容易理解,讀事務得到的鎖資源不釋放就有可能造成寫事務失敗或者寫事務得到的鎖資源不釋放就有可能造成讀事務

但是第一種讀讀事務也會造成死鎖嗎?

 

我這里做一個實驗

1、先確保數據庫沒有使用任何快照隔離級別

USE [tt1]
DBCC USEROPTIONS

 

 

2、腳本1

USE [tt1];

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN
SELECT * FROM [dbo].[Table_1] WITH (ROWLOCK)  WHERE [q]=88

 

 

3、腳本2

USE [tt1];

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

SELECT * FROM [dbo].[Storage] WITH (TABLOCKX)

SELECT * FROM [dbo].[Table_1] WHERE [q]=7

 

 

4、腳本3

USE [tt1];

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN
SELECT * FROM [dbo].[Table_1] WITH (ROWLOCK) WHERE [q]=88

 

 

5、腳本4

USE [tt1];

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN
SELECT * FROM [dbo].[Table_1] WITH (ROWLOCK) 

 

 

6、在多個查詢窗口(session)里執行上面的腳本

 

 

7、打開跟蹤標記

 DBCC TRACEON (1204, 1222, -1);
 DBCC tracestatus

 

 

8、過一會兒就會看到其中一個session 59已經作為死鎖犧牲品

 

9、在errorlog里已經看到spid為4的死鎖監視器(LOCK MONITOR)已經監測到死鎖的存在

EXEC xp_readerrorlog 0,1,NULL,NULL,'2015-08-06','2015-10-10','DESC'

 


總結

多人都不了解為什么SELECT語句也會產生死鎖,其實SELECT語句一般在RC隔離級別下很少會發送死鎖,只是用戶在日常開發中會使用了一些不恰當的鎖提示(Lock Hint)或者提升了事務隔離級別而導致

日常開發中我們都要注意不要濫用鎖提示(Lock Hint),根據實際情況進行判斷,該提升事務隔離級別就提升事務隔離級別,以免造成不必要的死鎖。

 

 

如有不對的地方,歡迎大家拍磚o(∩_∩)o 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜

    AutoPoster 發表在 痞客邦 留言(0) 人氣()