阻塞就是常說的等待,是指事務A等待特定的資源獲得知足以後,才能繼續執行下去。發生阻塞的另一種狀況是被其餘事務阻塞。阻塞對性能的影響,有時會比死鎖更嚴重,這是由於死鎖持續的時間很是短,SQL Server 一旦探測到死鎖的發生,就會當即殺死一個進程,以結束死鎖,使其餘進程可以正常運行下去。然而,阻塞不會被殺死,能夠持續很長很長時間,這就使得被阻塞的進程即便瞬間就能夠完成,也必須等待資源獲得知足才能執行下去。sql
一,探測阻塞
使用下面的腳本探測到當前活躍的阻塞:數據庫
select w.session_id as waiting_session_id
,w.waiting_task_address
,w.wait_type
,w.wait_duration_ms/1000 as duration_s
,db_name(k.resource_database_id) as resource_db_name
,k.resource_type
,k.resource_associated_entity_id
,w.resource_description
,k.request_mode
,k.request_type
,k.request_status
,w.blocking_session_id
,w.blocking_task_address
from sys.dm_os_waiting_tasks as w
inner join sys.dm_tran_locks as k
on w.resource_address=k.lock_owner_address
where w.wait_duration_ms>5000
and w.session_id>50
SQL Server 沒有記錄阻塞的歷史信息,只有一個關於等待的統計信息,若是要查看數據庫系統曾經遇到過的全部等待消息,那麼就須要手動記錄阻塞的信息。session
二,捕獲阻塞
要想捕獲阻塞相關的信息,最方便的選項是經過SQL Server Profiler,並把數據保存到表以對阻塞進行分析。數據結構
配置SQL Server Profiler捕獲阻塞相關的數據,首先打開SSMS的Tools菜單,打開SQL Server Profiler,在Events Selection中勾選Blocked process report 事件,並勾選全部的列,保存足夠多的信息:分佈式
Blocked process report 代表一個Task被阻塞時間超過了一個閾值,該閾值能夠經過 sys.sp_configue命令來設置。性能
在啓動SQL Server Profiler以前,請務必配置 blocked process threshold 選項:spa
sp_configure 'show advanced options', 1
go
reconfigure
go
sp_configure 'blocked process threshold', 20
go
reconfigure
go
三,即時查看阻塞的動態管理視圖
一般狀況下,使用下面4個DMV來查看阻塞的信息。線程
1,sys.dm_os_waiting_taskscode
該視圖返回正在等待的task信息,字段分爲兩組:申請資源的Task和擁有資源的Task,簡稱爲等待組(Task或Session)和阻塞組(Task 或 Session),等待組在申請資源時因爲資源被阻塞組佔用而必須等待,阻塞組擁有資源。server
- 字段waiting_task_address :表示申請資源的Task的內存地址,記做等待Task,該Task在申請資源時,因爲資源沒法被知足而被迫阻塞。
- 字段blocking_task_address:表示擁有資源的Task的內存地址,記做阻塞Task,該Task當前擁有資源,只有該Task釋放資源,被阻塞的Task(即 waiting_task_address )才能得到資源的使用權。
該視圖的字段解釋:
- waiting_task_address:處於等待資源狀態的Task地址(即 等待Task)
- session_id:與「等待Task」相關聯的Session的 ID(處於等待狀態的Session)。
- exec_context_id:與「等待Task」關聯的執行上下文的 ID。
- wait_type:等待類型的名稱。
- wait_duration_ms:此等待類型的總等待時間(毫秒),此時間包含 signal_wait_time。
- resource_address:該「等待Task」等待的資源地址,該字段能夠和 sys.dm_tran_locks 的lock_owner_address字段關聯起來
- blocking_task_address:當前持有此資源的Task的地址(即 阻塞Task)。
- blocking_session_id:阻塞 「等待Task」的Session ID,也就是說,該Session擁有資源,阻塞了 「等待Task」 對資源的請求:
- 若是此列值爲 NULL,則表示當前請求未被阻塞,或阻塞會話的信息不可用(或沒法進行標識)。
- -2 = 阻塞資源由孤立的分佈式事務擁有。
- -3 = 阻塞資源由延遲的恢復事務擁有。
- -4 = 因爲內部閂鎖狀態轉換而沒法肯定阻塞閂鎖全部者的會話 ID。
- blocking_exec_context_id:「阻塞Task」的執行上下文 ID。
- resource_description:爭用的資源描述
2, sys.dm_tran_locks
該視圖返回當前活躍的鎖管理器資源的信息,每一行表明一個向鎖管理器申請鎖的請求,該請求當前是活躍的,申請的鎖已經被授予或者正在等待被授予。
該視圖的字段主要分爲兩類,資源和請求,資源組描述鎖定的資源,請求組描述鎖的請求,主要字段解釋:
- resource_type:鎖定的資源類型,常見的資源類型是 OBJECT、PAGE、KEY、EXTENT、RID、HOBT 等。
- resource_subtype:鎖定的資源類型的子類型,是對 resource_type的細分
- resource_database_id:此資源位於其範圍以內的數據庫的 ID。由鎖管理器處理的全部資源均按數據庫 ID 劃分範圍。
- resource_description:資源描述
- resource_associated_entity_id:數據庫中與資源相關聯的實體的 ID。該值能夠是對象 ID、Hobt ID 或分配單元 ID,具體視資源類型而定。
- resource_lock_partition:已分區鎖資源的鎖分區 ID。對於未分區鎖資源,該值爲 0。
- request_mode:請求的模式。對於已授予的請求,爲已授予模式;對於等待請求,爲正在請求的模式。
- request_type:請求類型,該值爲 LOCK。
- request_status:用於描述請求的狀態,可能值爲 GRANTED、CONVERT和 WAIT,granted 表示請求者(requestor)已經被受權,容許鎖定資源;wait 表示請求者尚未被受權鎖定資源, convet 表示請求者已經被受權,等待鎖定資源。
- request_reference_count:同一請求程序已請求該資源的近似次數。
- request_session_id:當前擁有該請求的會話 ID
- request_exec_context_id:當前擁有該請求的進程的執行上下文ID。
- request_request_id:當前擁有該請求的進程的Request ID(即 Batch ID)
- request_owner_type:擁有該請求的實體類型。鎖管理器請求能夠由多種實體所擁有,可能的值有:
- TRANSACTION = 請求由事務全部。
- CURSOR = 請求由遊標全部。
- SESSION = 請求由用戶會話全部。
- SHARED_TRANSACTION_WORKSPACE = 請求由事務工做區的共享部分全部。
- EXCLUSIVE_TRANSACTION_WORKSPACE = 請求由事務工做區的排他部分全部。
- NOTIFICATION_OBJECT =請求由內部的SQL Server組件全部
- request_owner_id:請求的特定全部者 ID,分兩種狀況,第一種狀況是:事務是該請求的全部者,request_owner_id值是事務ID。 第二種狀況:
- 若是FileTable是該請求的全部者,request_owner_id值 爲 -4 表示FileTable持有database lock; request_owner_id值爲 -3 表示 FileTable持有table lock。
- 若是是其餘值,request_owner_id值表明文件句柄,在sys.dm_filestream_non_transacted_handles 中顯示爲fcb_id字段。
- lock_owner_address:用於跟蹤該請求的內部數據結構的內存地址。該列能夠與 sys.dm_os_waiting_tasks 中的 resource_address 列鏈接。
3,sys.dm_os_wait_stats
等待統計,統計數據庫系統中出現的等待:
- wait_type:等待類型的名稱。
- waiting_tasks_count:該等待類型的等待次數
- wait_time_ms:該等待類型的總等待時間(毫秒)
- max_wait_time_ms:該等待類型的最長等待時間。
- signal_wait_time_ms:正在等待的線程從收到信號通知到開始運行之間的時差。
4,sys.dm_os_tasks
返回當前SQL Server實例中活躍的Task:
- task_address:Task結構的內存地址
- task_state:Task的狀態,有效值有:PENDING、RUNNABLE、RUNNING、SUSPENDED、DONE和SPINLOOP
- context_switches_count:Task已經完成的調度程序上下文切換的次數
- pending_io_count:該Task執行的物理IO的次數
- pending_io_byte_count:該Task執行的物理IO的字節總數量
- pending_io_byte_average:Task執行的物理IO的字節平均數量
- scheduler_id:父調度程序的ID,這是調度程序的句柄
- session_id:該Task關聯的Session ID
- exec_context_id:該Task關聯的執行上下文ID
- request_id:該Task處理的請求 ID
- worker_address:執行該Task的Worker的內存地址,若是該值爲NULL,表示該Task等待Worker去執行,或者已經執行完成。
- host_address:host的內存地址
- partner_task_address:該Task的父Task的內存地址
參考文檔:
sys.dm_tran_locks