1. 程式人生 > >如何監控和解決SQL Server的阻塞(1) (當前阻塞)

如何監控和解決SQL Server的阻塞(1) (當前阻塞)

host tab tool alt 現象 dmv fonts 毫秒 .text

1. 什麽是"阻塞"?

阻塞是SQL數據庫應用"鎖"機制的一個副作用。當一個應用請求針對某個數據庫對象(例如全表,某行數據, 或者是某個數據頁)加鎖後,那麽這個鎖會阻塞其它的應用請求。這就好像你把家裏的大門上了鎖,你的老婆沒有鑰匙,只能等待你回家。她進入房間的請求被你阻塞了,不得不等待,直到你解鎖開門。對於數據庫來說短暫的阻塞是可以被接受的。而且短暫的阻塞也是數據庫的常態。只有當阻塞的時間超過了人們的容忍時間,這種阻塞現象需要DBA的關註。

2. 如何發現"當前"的"阻塞"?

通過下列工具可以發現當前正在發生的阻塞現象

  • 活動監視器 Activity Monitor
  • sp_who2
  • 動態性能視圖(DMV)
  • 會話 ID: 是建立連接時分配給每個用戶連接的唯一整數 (int)。
  • 等待時間(毫秒):此任務等待資源所用的時間(毫秒)。如果任務沒有等待,則等待時間為 0。
  • 等待類型:最近或當前等待類型的名稱。
  • 等待資源:所需資源的名稱。
  • 阻塞者:如果有阻塞會話,則為正阻塞任務的會話的 ID。
  • 頭阻塞程序:如果有阻塞會話,則標識導致第一個阻塞條件的會話。值為 1 表示其他會話的頭阻塞程序。

技術分享圖片

2.2 sp_who2

在master數據庫下,運行如下語句: 

[sql] view plain copy 技術分享圖片技術分享圖片
  1. exec sp_who2

你會看到下面的信息,它類似活動監視器,顯示當前用戶請求的阻塞信息.只是表格化了,便於我們過濾一些不相關的內容.

技術分享圖片

通過下面的語句可以將sp_who2的顯示信息導入到一張臨時表裏.當然你也可以導入到一張永久表裏.

[sql] view plain copy 技術分享圖片技術分享圖片
  1. CREATETABLE #sp_who2 (SPID INT,Status VARCHAR(255),
  2. Login VARCHAR(255),HostName VARCHAR(255),
  3. BlkBy VARCHAR(255),DBName VARCHAR(255),
  4. Command VARCHAR(255),CPUTime INT,
  5. DiskIO INT,LastBatch VARCHAR(255),
  6. ProgramName VARCHAR(255),SPID2 INT,
  7. REQUESTID INT)
  8. INSERTINTO #sp_who2 EXECsp_who2
  9. SELECT *
  10. FROM #sp_who2
  11. WHERE DBName <> ‘master‘
  12. ORDER BY DBName ASC
  13. DROP TABLE #sp_who2

2.3 使用動態性能視圖 (推薦)

動態性能視圖展示了更多更豐富的信息,幫助DBA快速診斷"當前"的阻塞現象. 它還能捕獲諸如SQL語句和執行當前SQL語句已經使用的CPU時間, 內存大小,運行總時間,邏輯讀數等.


use [master]
GO
SELECT
DB_NAME(Blocked.database_id) AS ‘database‘,
Blocked.Session_ID AS ‘blocked SPID‘,
Blocked_SQL.TEXT AS ‘blocked SQL‘,
Waits.wait_type AS ‘wait resource‘,
Blocking.Session_ID AS ‘blocking SPID‘,
Blocking_SQL.TEXT AS ‘blocking SQL‘,
sess.status AS ‘blocking status‘,
sess.total_elapsed_time AS ‘blocking elapsed time‘,
sess.logical_reads AS ‘blocking logical reads‘,
sess.memory_usage AS ‘blocking memory usage‘,
sess.cpu_time AS ‘blocking cpu time‘,
sess.program_name AS ‘blocking program‘,
GETDATE() AS ‘timestamp‘
FROM sys.dm_exec_connections AS Blocking
INNER JOIN sys.dm_exec_requests AS Blocked ON Blocked.Blocking_Session_ID = Blocking.Session_ID
INNER JOIN sys.dm_os_waiting_tasks AS Waits ON waits.Session_ID = Blocked.Session_ID
INNER JOIN sys.dm_exec_sessions sess ON sess.session_id = Blocking.Session_ID
CROSS APPLY sys.dm_exec_sql_text(Blocking.most_recent_sql_handle) AS Blocking_SQL
CROSS APPLY sys.dm_exec_sql_text(Blocked.sql_handle) AS Blocked_SQL

如何監控和解決SQL Server的阻塞(1) (當前阻塞)