當同個對象上有互斥的鎖存在時,查詢需要等待很長時間,我們是否可以收到來自SQL Server提醒?答案是可以的,做法非常簡單,因為SQL Server為你提供了稱為Blocked Process Report 的功能。很可惜這個功能默認是未啟用的。因此這篇文章我想給你講解下Blocked Process Report 的大致用法,當SQL Server出現鎖時,你可以用它來做的進一步的故障排除。
Blocked Process Report本身是個簡單的事件,你可以通過SQL Server Profiler或SQL Traces跟蹤。這個事件被稱為Blocked Process Report,你可以在Errors and Warnings事件組里找到它:
但那個事件只被突出(跟蹤),當你通過sp_configure選項指定blocked process threshold閥值在SQL Server實例級別啟用Blocked Process Report 功能時。那個參數只接收0到86400的數字,查詢必須要等到鎖持久的秒數后,SQL Server才會生成Blocked Process Report事件。默認情況下那個配置選項值為0,就是這個事件不會觸發。下面的代碼設置閥值為10秒鐘:
1 sp_configure 'blocked process threshold', 102 RECONFIGURE3 GO
為了演示Blocked Process Report,我通過一個UPDATE語句在AdventureWorks2008R2數據庫內部創建一個新的事務:
1 BEGIN TRANSACTION2 3 UPDATE Person.Person4 SET Title = 'Mr'5 WHERE BusinessEntityID = 1
在這個語句執行后,這個查詢現在需要在列BusinessEntityID值等于1的記錄上獲得一個排它鎖(Exclusive Lock (X))。在第2個會話現在我嘗試讀取同樣的記錄。在讀取期間,SQL Server嘗試獲取一個共享鎖(Shared Lock (S)),這就導致了阻塞情形:
1 SELECT * FROM Person.Person2 WHERE BusinessEntityID = 13 GO
當你啟動SQL Server Profiler且配置了Blocked Process Report事件,在10秒后,你就會看這個被報告:
從上圖可以看到,Blocked Process Report 本身就是一個xml數據,因此很容易對它進一步分析,如果你對XML和XQuery熟悉的話。
1 <blocked-process-report> 2 <blocked-process> 3 <process id="process35ab1c8" taskpriority="0" logused="0" waitresource="KEY: 11:72057594045333504 (8194443284a0)" waittime="16986" ownerId="49004" transactionname="SELECT" lasttranstarted="2015-06-23T14:09:38.900" XDES="0x5f02138" lockMode="S" schedulerid="1" kpid="8512" status="suspended" spid="55" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2015-06-23T14:09:38.900" lastbatchcompleted="2015-06-23T14:09:10.877" lastattention="2015-06-23T14:09:10.877" clientapp="Microsoft SQL Server Management Studio - 查詢" hostname="WXGFZCXXZX81-18" hostpid="4492" loginname="sa" isolationlevel="read committed (2)" xactid="49004" currentdb="11" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200"> 4 <executionStack> 5 <frame line="1" stmtstart="24" sqlhandle="0x020000006063873a3a5f7e72ad0b55e66df822bf70e6f14c"/> 6 <frame line="1" sqlhandle="0x0200000066bba411d9c6966611de8194e81441d7836a9554"/> 7 </executionStack> 8 <inputbuf> 9 SELECT * FROM Person.Person10 WHERE BusinessEntityID = 111 </inputbuf>12 </process>13 </blocked-process>14 <blocking-process>15 <process status="sleeping" spid="57" sbid="0" ecid="0" priority="0" trancount="3" lastbatchstarted="2015-06-23T14:09:36.050" lastbatchcompleted="2015-06-23T14:09:36.050" clientapp="Microsoft SQL Server Management Studio - 查詢" hostname="WXGFZCXXZX81-18" hostpid="4492" loginname="sa" isolationlevel="read committed (2)" xactid="47048" currentdb="11" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">16 <executionStack/>17 <inputbuf>18 BEGIN TRANSACTION19 20 UPDATE Person.Person21 SET Title = 'Mr'22 WHERE BusinessEntityID = 1 </inputbuf>23 </process>24 </blocking-process>25 </blocked-process-report>
XML數據里有2個重要節點– <blocked-process> 和<blocking-process>。第1個– <blocked-process>描述阻塞的會話。在這里是對AdventureWorks2008R2執行SELECT語句查詢的會話。這里最重要的是waitresource的XML屬性,它包含會話上等待的鎖資源,超過了blocked process threshold 配置選項。
第2個<blocking-process>描述當前在資源上持互斥鎖的會話,在這個資源上其他會話需要獲取鎖。這里最重要的是<inputbuf>的XML元素,它顯示了SQL 語句需要的互斥鎖。手上有了這些信息,就很容易進一步進行故障排除,就是為什么阻塞閥值被超出,還有下一步對它如何處理(這里的會話是一個孤立的事務(orphaned transaction),殺掉了其他會話)。
當你使用Blocked Process Report時,你需要記住的最重要的是,SQL Server值為你生成對應的XML報告,不會為你解決鎖/死鎖。這就是,在生成Blocked Process Report后,SELECT語句的會話還是繼續運行——SQL Server這里不會殺掉這個會話——SQL Server只報告有個會話超過了blocked process threshold——剩下的一切都還是要你自己去處理。
新聞熱點
疑難解答