偵測阻塞語句


前言:

如果一個事務正在等待一些給其他事務鎖定的資源。這個事務就被成為“被阻塞的事務”。反過來,引起阻塞的事務,也就是鎖定資源並造成其他事務等待的事務叫做“正在阻塞的事務”。

長時間運行事務會阻塞其他事務和查詢,使他們等待長時間。在繁重的系統中,很多時候我們會遇到阻塞問題,如果一個事務因為阻塞未完成。會造成一些列的等待鏈。

本文將介紹如何發現並馬上解決這方面的問題。

 

准備工作:

本例依舊使用SQLServer2012上的AdventureWorks2012數據庫。

 

步驟:

1、 連到SQLServer2012的AdventureWorks2012數據庫。

2、 新建窗口並輸入:

[sql] view plaincopyprint?
  1. USE AdventureWorks2012  
  2. GO  
  3. SET TRANSACTION ISOLATION LEVEL REPEATABLE READ  
  4. GO  
  5.   
  6. --開啟事務  
  7. BEGIN TRANSACTION  
  8.   
  9. --獲取會話ID  
  10. SELECT  @@SPID AS Connection1_SessionID  
  11.   
  12. SELECT  *  
  13. FROM    Sales.SalesOrderDetail  
  14. WHERE   SalesOrderDetailID = 121316  


3、 執行完之后,截圖如下:


4、 新開另外一個窗口,輸入下面代碼去開啟另外一個事務,留意UPDATE語句,將不會執行,因為在等待第二步中的事務:


[sql] view plaincopyprint?
  1. USE AdventureWorks2012  
  2. GO  
  3.   
  4. --開啟事務  
  5. BEGIN TRANSACTION  
  6.   
  7. UPDATE  Sales.SalesOrderDetail  
  8. SET     OrderQty = 10  
  9. WHERE   SalesOrderDetailID = 121316  
  10.   
  11. COMMIT TRANSACTION  


5、 再開啟一個事務,輸入以下代碼查詢被阻塞和正在阻塞的查詢: 

[sql] view plaincopyprint?
  1. SELECT  R.session_id AS BlockedSessionID ,  
  2.         S.session_id AS BlockingSessionID ,  
  3.         Q1.text AS BlockedSession_TSQL ,  
  4.         Q2.text AS BlockingSession_TSQL ,  
  5.         C1.most_recent_sql_handle AS BlockedSession_SQLHandle ,  
  6.         C2.most_recent_sql_handle AS BlockingSession_SQLHandle ,  
  7.         S.original_login_name AS BlockingSession_LoginName ,  
  8.         S.program_name AS BlockingSession_ApplicationName ,  
  9.         S.host_name AS BlockingSession_HostName  
  10. FROM    sys.dm_exec_requests AS R  
  11.         INNER JOIN sys.dm_exec_sessions AS S ON R.blocking_session_id = S.session_id  
  12.         INNER JOIN sys.dm_exec_connections AS C1 ON R.session_id = C1.most_recent_session_id  
  13.         INNER JOIN sys.dm_exec_connections AS C2 ON S.session_id = C2.most_recent_session_id  
  14.         CROSS APPLY sys.dm_exec_sql_text(C1.most_recent_sql_handle) AS Q1  
  15.         CROSS APPLY sys.dm_exec_sql_text(C2.most_recent_sql_handle) AS Q2  


--為了方面了解查詢出來的字段含義,個人在原來語句基礎上稍微改動了下:

SELECT R.blocking_session_id 阻塞會話進程ID,
  R.session_id 被阻塞會話進程ID,
  t1.text 阻塞進程SQL語句,
  T2.text 被阻塞進程SQL語句,
  s.host_name 阻塞進程主機名 ,
  s.login_name 阻塞進程登錄名,
  S2.host_name 被阻塞進程主機名,
  s2.login_name 被阻塞進程登錄名
FROM SYS.dm_exec_requests R
INNER JOIN SYS.dm_exec_sessions S ON R.blocking_session_id=S.session_id
INNER JOIN SYS.dm_exec_connections C ON S.session_id=C.most_recent_session_id
CROSS APPLY SYS.dm_exec_sql_text(C.MOST_RECENT_SQL_HANDLE) T1
INNER JOIN SYS.dm_exec_connections C2 ON C2.MOST_RECENT_SESSION_ID=R.session_id
CROSS APPLY SYS.DM_EXEC_SQL_TEXT(C2.MOST_RECENT_SQL_HANDLE) T2
INNER JOIN SYS.dm_exec_sessions S2 ON R.session_id=S2.session_id


--cross applay若看不懂的話,請參考:http://blog.csdn.net/yabingshi_tech/article/details/24399243

6、 因為第一個連接占用了資源,阻塞了其他事務,所以這里要結束這個進程:


[sql] view plaincopyprint?
  1. KILL 68  
  2. GO  



7、 換回第二個查詢界面,發現update操作已經成功完成。上面的進程號根據不同機器而定。


分析:

在本例中,把事務隔離級別設為REPEATABLE READ,因為在這個隔離級別中,在資源上的共享鎖將持續到事務完成。所以當從表中查找數據是,該值上會加上共享鎖。在事務提交或回滾前不會釋放。

當執行第二個連接的update語句時,不能完成,因為被第一個事務阻塞了,且在REPEATABLE READ下共享鎖不釋放。

為了標識阻塞和被阻塞的請求,需要用到下面的DMO:

1、 dm_exec_requests

返回有關在 SQL Server 中執行的每個請求的信息。

可以看到阻塞進程相關信息。


2、 dm_exec_sessions

sys.dm_exec_sessions 是服務器范圍的視圖,顯示了有關所有活動用戶連接和內部任務的信息。

 此信息包含客戶端版本、客戶端程序名稱、客戶端登錄時間、登錄用戶、當前會話設置等。

使用 sys.dm_exec_sessions,首先可以查看當前的系統負荷並標識相關會話,然后可以通過其他動態管理視圖或動態管理函數了解有關該會話的詳細信息。


3、 dm_exec_connections

返回有關與此 SQL Server 實例建立的連接的信息以及每個連接的詳細信息。


4、 dm_exec_sql_text

返回由指定的 sql_handle 標識的 SQL 批處理的文本


本篇文章轉自:http://blog.csdn.net/dba_huangzj/article/details/8697578


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com