적용 대상:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Microsoft Fabric의 SQL 데이터베이스
데이터베이스 관리자는 데이터베이스 성능을 저해하는 잠금의 원인을 식별해야 하는 경우가 많습니다.
예를 들어 서버의 성능 문제가 차단으로 인해 발생할 수 있다고 의심합니다. sys.dm_exec_requests를 쿼리할 때 잠금이 대기 중인 리소스임을 나타내는 대기 유형이 있는 일시 중단 모드에서 여러 세션을 찾습니다.
sys.dm_tran_locks를 쿼리하면 많은 잠금이 미해결 상태임을 보여 주지만 잠금이 부여된 세션에는 sys.dm_exec_requests 표시되는 활성 요청이 없습니다.
이 예제에서는 잠금을 수행한 쿼리, 쿼리 계획 및 잠금이 수행된 시점의 Transact-SQL 스택을 결정하는 방법을 보여 줍니다. 이 예제에서는 확장 이벤트 세션에서 페어링 대상이 사용되는 방법도 보여 줍니다.
이 태스크를 수행하려면 SQL Server Management Studio에서 쿼리 편집기를 사용하여 다음 절차를 수행해야 합니다.
참고 항목
이 예에서는 AdventureWorks 데이터베이스를 사용합니다.
잠금을 보유한 쿼리를 파악하려면
쿼리 편집기에서 다음 문을 실행합니다.
-- Perform cleanup. IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='FindBlockers') DROP EVENT SESSION FindBlockers ON SERVER GO -- Use dynamic SQL to create the event session and allow creating a -- predicate on the AdventureWorks database id. -- DECLARE @dbid int SELECT @dbid = db_id('AdventureWorks') IF @dbid IS NULL BEGIN RAISERROR('AdventureWorks is not installed. Install AdventureWorks before proceeding', 17, 1) RETURN END DECLARE @sql nvarchar(1024) SET @sql = ' CREATE EVENT SESSION FindBlockers ON SERVER ADD EVENT sqlserver.lock_acquired (action ( sqlserver.sql_text, sqlserver.database_id, sqlserver.tsql_stack, sqlserver.plan_handle, sqlserver.session_id) WHERE ( database_id=' + cast(@dbid as nvarchar) + ' AND resource_0!=0) ), ADD EVENT sqlserver.lock_released (WHERE ( database_id=' + cast(@dbid as nvarchar) + ' AND resource_0!=0 )) ADD TARGET package0.pair_matching ( SET begin_event=''sqlserver.lock_acquired'', begin_matching_columns=''database_id, resource_0, resource_1, resource_2, transaction_id, mode'', end_event=''sqlserver.lock_released'', end_matching_columns=''database_id, resource_0, resource_1, resource_2, transaction_id, mode'', respond_to_memory_pressure=1) WITH (max_dispatch_latency = 1 seconds)' EXEC (@sql) -- -- Create the metadata for the event session -- Start the event session -- ALTER EVENT SESSION FindBlockers ON SERVER STATE = START서버에서 작업을 실행한 후 쿼리 편집기에서 다음 문을 실행하여 여전히 잠금을 보유하고 있는 쿼리를 찾습니다.
-- -- The pair matching targets report current unpaired events using -- the sys.dm_xe_session_targets dynamic management view (DMV) -- in XML format. -- The following query retrieves the data from the DMV and stores -- key data in a temporary table to speed subsequent access and -- retrieval. -- SELECT objlocks.value('(action[@name="session_id"]/value)[1]', 'int') AS session_id, objlocks.value('(data[@name="database_id"]/value)[1]', 'int') AS database_id, objlocks.value('(data[@name="resource_type"]/text)[1]', 'nvarchar(50)' ) AS resource_type, objlocks.value('(data[@name="resource_0"]/value)[1]', 'bigint') AS resource_0, objlocks.value('(data[@name="resource_1"]/value)[1]', 'bigint') AS resource_1, objlocks.value('(data[@name="resource_2"]/value)[1]', 'bigint') AS resource_2, objlocks.value('(data[@name="mode"]/text)[1]', 'nvarchar(50)') AS mode, objlocks.value('(action[@name="sql_text"]/value)[1]', 'varchar(MAX)') AS sql_text, CAST(objlocks.value('(action[@name="plan_handle"]/value)[1]', 'varchar(MAX)') AS xml) AS plan_handle, CAST(objlocks.value('(action[@name="tsql_stack"]/value)[1]', 'varchar(MAX)') AS xml) AS tsql_stack INTO #unmatched_locks FROM ( SELECT CAST(xest.target_data as xml) lockinfo FROM sys.dm_xe_session_targets xest JOIN sys.dm_xe_sessions xes ON xes.address = xest.event_session_address WHERE xest.target_name = 'pair_matching' AND xes.name = 'FindBlockers' ) heldlocks CROSS APPLY lockinfo.nodes('//event[@name="lock_acquired"]') AS T(objlocks) -- -- Join the data acquired from the pairing target with other -- DMVs to return provide additional information about blockers -- SELECT ul.* FROM #unmatched_locks ul INNER JOIN sys.dm_tran_locks tl ON ul.database_id = tl.resource_database_id AND ul.resource_type = tl.resource_type WHERE resource_0 IS NOT NULL AND session_id IN (SELECT blocking_session_id FROM sys.dm_exec_requests WHERE blocking_session_id != 0) AND tl.request_status='wait' AND REPLACE(ul.mode, 'LCK_M_', '' ) = tl.request_mode문제를 식별한 후 임시 테이블과 이벤트 세션을 삭제합니다.
DROP TABLE #unmatched_locks DROP EVENT SESSION FindBlockers ON SERVER
참고 항목
앞의 Transact-SQL 코드 예제는 SQL Server 온-프레미스에서 실행되지만 Azure SQL Database에서는 실행되지 않을 수 있습니다. 이벤트와 직접 관련된 예제의 핵심 부분(예: ADD EVENT sqlserver.lock_acquired와 같은 Azure SQL Database에서도 작동). 그러나 예를 실행하려면 sys.server_event_sessions 같은 예비 항목을 sys.database_event_sessions 같은 Azure SQL Database 대응 항목으로 편집해야 합니다.
SQL Server 온-프레미스와 Azure SQL Database 간의 이러한 사소한 차이점에 대한 자세한 내용은 다음 문서를 참조하세요.
참고 항목
CREATE EVENT SESSION(Transact-SQL)
ALTER EVENT SESSION(Transact-SQL)
DROP EVENT SESSION(Transact-SQL)
sys.dm_xe_session_targets(Transact-SQL)
sys.dm_xe_sessions(Transact-SQL)