Sql-Server
如何確定哪個語句阻止 SQL Server 中的更新
我們有一個在大型 J2EE 應用程序中執行的 UPDATE 語句,該應用程序被其他語句阻塞。更新使用的是主鍵,所以它應該只影響一行。應用程序中使用的隔離級別應該是 READ UNCOMMITTED,所以它應該只是另一個導致阻塞的修改,但我們看不到在哪裡。
我們已經獲得了所有阻塞事務的報告,這確實表明會話阻塞了更新。使用該
DBCC INPUTBUFFER
命令顯示了阻塞會話執行的最後一條語句,但這是另一個表上的 SELECT,而不是 UPDATE,所以我認為這不是原因。我認為它必須是交易中較早的聲明。在這一點上,我的 SQL Server 知識枯竭了,而且我在重現問題時也遇到了問題;它間歇性地發生。
我應該知道採取哪些步驟來找到阻止聲明?
在執行更新之前:
SELECT @@SPID;
現在,執行更新,如果它沒有足夠快地完成,那麼在另一個視窗中執行:
SELECT status, command, wait_type, last_wait_type, blocking_session_id FROM sys.dm_exec_requests WHERE session_id = <@@SPID from above>;
如果您在 中獲得一個值
blocking_session_id
,則可以對該 SPID 執行相同的查詢。你也可以說:DBCC INPUTBUFFER(<blocking spid>);
(好吧,只要您不在 SQL Azure 上。)
如果這沒有產生線索,那麼阻塞語句可能實際上位於更大事務中的不同點。您必須通過確定該 spid 的執行位置以及它是否是一組臨時 T-SQL、儲存過程等來跟踪它。“看這裡”真的沒有什麼神奇的!我們可以為您提供。
如果它沒有被阻止,您可能會在其他列中找到相關資訊,這些資訊可以幫助確定它緩慢的原因(例如,它可能正在等待一個巨大的日誌自動增長事件)。
鑑於我無法將此解釋添加為評論,因此我正在添加答案。但這只是對@Aaron Bertrand 答案的補充:
您的聲明可能正在等待另一個也在等待的聲明。我剛剛添加了 Aaron 的 SELECT 幾次。重複,直到你看到一個正在執行。那可能是問題所在:
Declare @blc int SELECT @blc = blocking_session_id FROM sys.dm_exec_requests WHERE session_id = 109 --Use the SPID here SELECT status, command, wait_type, last_wait_type, blocking_session_id FROM sys.dm_exec_requests WHERE session_id = @blc DBCC INPUTBUFFER(@blc); DECLARE @blc2 int SELECT @blc2 = blocking_session_id FROM sys.dm_exec_requests WHERE session_id = @blc SELECT status, command, wait_type, last_wait_type, blocking_session_id FROM sys.dm_exec_requests WHERE session_id = @blc2 DBCC INPUTBUFFER(@blc2); DECLARE @blc3 int SELECT @blc3 = blocking_session_id FROM sys.dm_exec_requests WHERE session_id = @blc2 SELECT status, command, wait_type, last_wait_type, blocking_session_id FROM sys.dm_exec_requests WHERE session_id = @blc3 DBCC INPUTBUFFER(@blc3); DECLARE @blc4 int SELECT @blc4 = blocking_session_id FROM sys.dm_exec_requests WHERE session_id = @blc3 SELECT status, command, wait_type, last_wait_type, blocking_session_id FROM sys.dm_exec_requests WHERE session_id = @blc4 DBCC INPUTBUFFER(@blc4);