1. 程式人生 > 其它 >Sql Server事務+隔離級別+阻塞+死鎖

Sql Server事務+隔離級別+阻塞+死鎖

技術標籤:Sql Serversqlserver

背景

分析事務的執行過程

寫在前面

摘錄自https://www.cnblogs.com/jackson0714/p/TSQLFundamentals_08.html
link

分析當前查詢中的鎖

sys.dm_tran_locks 檢視

SELECT  request_session_id AS 會話id ,
        resource_type AS 請求鎖定的資源型別 ,
        resource_description AS 描述 ,
        request_mode AS 模式 ,
        request_status AS
狀態 FROM sys.dm_tran_locks

分析阻塞
1.sys.dm_tran_locks 檢視
(1)該動態檢視可以查詢出哪些資源被哪個程序ID鎖了
(2)查詢出對資源授予或正在等待的鎖模式
(3)查詢出被鎖定資源的型別

在這裡插入圖片描述

sys.dm_exec_connections 檢視

SELECT  session_id ,
        connect_time ,
        last_read ,
        last_write ,
        most_recent_sql_handle
FROM    sys.dm_exec_connections
 
WHERE
session_id IN ( 55 )

2.sys.dm_exec_connections 檢視
(1)查詢出該動態檢視可以查詢出程序相關的資訊
(2)查詢出最後一次發生讀操作和寫操作的時間last_read,last_write
(3)查詢出程序執行的最後一個SQL批處理的二進位制標記most_recent_sql_handle

sys.dm_exec_sql_text 表函式

SELECT  session_id ,
        text
FROM    sys.dm_exec_connections
        CROSS APPLY sys.dm_exec_sql_text
        (
most_recent_sql_handle) AS ST WHERE session_id IN ( 55 )

3.sys.dm_exec_sql_text 表函式
(1)該函式可以將二進位制標記most_recent_sql_handle作為引數,然後返回SQL程式碼。
(2)阻塞程序在不斷地執行,所以在程式碼中看到的最後一個操作不一定是導致問題的語句。在本例中最後一條執行語句是導致阻塞的語句。

sys.dm_exec_sessions 檢視

SELECT * FROM sys.dm_exec_sessions where session_id = 55

4.sys.dm_exec_sessions 檢視
(1)會話建立的時間login_time
(2)特定於會話的客戶端工作站名稱host_name
(3)初始化會話的客戶端程式的名稱program_name
(4)會話所使用的SQL Server登入名login_name
(5)最近一次會話請求的開始時間last_request_start_time
(6)最近一次會話請求的完成時間last_request_end_time

sys.dm_exec_requests 檢視

SELECT * FROM sys.dm_exec_requests where session_id = 55

5.sys.dm_exec_requests 檢視
(1)識別出阻塞鏈涉及到的會話、爭用的資源、被阻塞會話等待了多長時間

Lock_TIMEOUT 選項

6.Lock_TIMEOUT 選項
(1)設定會話等待鎖釋放的超時期限
(2)預設情況下會話不會設定等待鎖釋放的超時期限
(3)設定會話超時期限為5秒, SET Lock_TIMEOUT 5000
(4)鎖定如果超時,不會引發事務回滾
(5)取消會話超時鎖定的設定,SET LOCK_TIMEOUT -1

KILL 命令

(1)殺掉會話52,KILL 52
(2)殺掉會話,會引起事務回滾,同時釋放排他鎖

隔離級別

已提交讀(READ COMMITTED)(預設值)

(1)未提交讀 (READ UNCOMMITTED)
(2)已提交讀(READ COMMITTED)(預設值)
(3)可重複讀(REPEATABLE READ)
(4)可序列化(SERIALIZABLE)
(5)快照(SNAPSHOT)
(6)已經提交讀快照(READ_COMMITTED_SNAPSHOT)

設定整個會話的隔離級別

SET TRANSACTION ISOLATION LEVEL <isolation name>;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

用表提示設定查詢的隔離級別

SELECT ... FROM <table> WITH (<isolation name>);<br>
SELECT * FROM dbo.myProduct WITH (READCOMMITTED);

注意:
1.設定會話選項的隔離級別時,隔離級別中的每個單詞之間需要用空格分隔
2.用表提示的隔離級別時,隔離級別中的每個單詞之間不需要用空格分隔
3.表提示的隔離級別有同義詞,如:NOLOCK->READUNCOMMITTED,HOLDLOCK->REPEATABLEREAD
4.隔離級別的嚴格性:1.未提交讀<2.已提交讀<3.可重複讀<4.可序列化
5.隔離級別越高,一致性越高,併發性越低
6.基於快照的隔離級別,SQL Server將提交過的行儲存到tempdb資料庫中,當讀操作發現行的當前版本和它們預期的不一致時,可以立即得到行的以前版本,從而不用請求共享鎖也能取得預期的一致性。

表提示的隔離級別有同義詞,如:NOLOCK->READUNCOMMITTED,HOLDLOCK->REPEATABLEREAD

1. 未提交讀 (READ UNCOMMITTED),隔離級別的含義:
(1)讀操作可以讀取未提交的修改(也稱為髒讀)。
(2)讀操作不會妨礙寫操作請求排他鎖,其他事務正在進行讀操作時,
	寫操作可以同時對這些資料進行修改。
(3)事務A進行了多次修改,事務B在不同階段進行查詢時可能會有不同的結果。
2.已提交讀(READ COMMITTED)(預設值)
(1)必須獲得共享鎖才能進行讀操作,其他事務如果對該資源持有排他鎖,則共享鎖必須等待排他鎖釋放。
(2)讀操作不能讀取未提交的修改,讀操作讀取到的資料是提交過的修改。
(3)讀操作不會在事務持續期間內保留共享鎖,
	其他事務可以在兩個讀操作之間更改資料資源,
	讀操作因而可能每次得到不同的取值。這種現象稱為“不可重複讀”
3.可重複讀 (REPEATABLE READ),隔離級別的含義:
(1)必須獲得共享鎖才能進行讀操作,獲得的共享鎖將一直保持直到事務完成之止。
(2)在獲得共享鎖的事務完成之前,沒有其他事務能夠獲得排他鎖修改這一資料資源,
	這樣可以保證實現可重複的讀取。
(3)兩個事務在第一次讀操作之後都將保留它們獲得的共享鎖,
	所以任何一個事務都不能獲得為了更新資料而需要的排他鎖,
	這種情況將會導致死鎖(deadlock),不過卻避免了更新衝突。

可重複讀 (REPEATABLE READ),將會導致死鎖(deadlock),不過卻避免了更新衝突。

4.可序列化(SERIALIZABLE),隔離級別的含義:
(1)必須獲得共享鎖才能進行讀操作,獲得的共享鎖將一直保持直到事務完成之止。
(2)在獲得共享鎖的事務完成之前,沒有其他事務能夠獲得排他鎖修改這一資料資源,
	且當其他事務增加能夠滿足當前事務的讀操作的查詢搜尋條件的新行時,其他事務將會被阻塞,
	直到當前事務完成然後釋放共享鎖,其他事務才能獲得排他鎖進行插入操作。
(3)事務中的讀操作在任何情況下讀取到的資料是一致的,不會出現幻影行(幻讀)。
(4)範圍鎖:讀操作鎖定滿足查詢搜尋條件範圍的鎖

隔離級別總結

髒讀:讀取未提交的更改。

不可重複讀:讀操作不會在事務持續期間內保留共享鎖,其他事務可以在兩個讀操作之間更改資料資源,讀操作因而可能每次得到不同的取值。

丟失更新:兩個事務進行讀操作,獲得資源上的共享鎖,讀取完資料後,不再持有資源上的任何鎖,兩個事務都能更新這個值,
最後進行更新的事務將會覆蓋其他事務做的更改,導致其他事務更改的資料丟失。

幻讀:第一次和第二次讀取到的資料行數不一致。

範圍鎖:讀操作鎖定滿足查詢搜尋條件範圍的鎖

在這裡插入圖片描述
摘錄自https://www.cnblogs.com/jackson0714/p/TSQLFundamentals_08.html(推薦閱讀)

本文說明,主要技術內容來自網際網路技術大佬的分享,還有一些自我的加工(僅僅起到註釋說明的作用)。如有相關疑問,請留言,將確認之後,執行侵權必刪