SQL Server에서 잠긴 테이블 또는 행 감지


20

차단 된 세션의 세부 정보를 추적하는 방법을 이해 / 학습하려고합니다.

그래서 다음 설정을 만들었습니다.

create table foo (id integer not null primary key, some_data varchar(20));
insert into foo values (1, 'foo');
commit;

이제 두 개의 다른 클라이언트에서 데이터베이스에 두 번 연결합니다.

첫 번째 세션에서는

begin transaction
update foo set some_data = 'update'
  where id = 1;

잠금을 유지하기 위해 명시 적으로 커밋 하지 않습니다 .

두 번째 세션에서는 잠금으로 인해 대기하는 것과 동일한 진술과 물론 발행합니다. 이제 세션 2가 foo테이블을 기다리고 있음을 확인하기 위해 떠 다니는 다른 쿼리를 사용하려고 합니다.

sp_who2 다음을 보여줍니다 (중요한 정보 만 표시하기 위해 일부 열을 제거했습니다).

SPID | 상태 | BlkBy | DB 이름 | 명령 | SPID | 요청
----- + -------------- + ------- + ---------- + ------------ -------- + ------ + ----------
52 | 자고 | . | foodb | 대기 명령 | 52 | 0        
53 | 자고 | . | foodb | 대기 명령 | 53 | 0        
54 | 일시 중지 | 52 | foodb | 업데이트 | 54 | 0        
56 | 실행 가능 | . | foodb | 안으로 선택 | 56 | 0        

세션 54의 커밋되지 않은 변경 사항으로 인해 세션 54가 차단됩니다.

쿼리 sys.dm_os_waiting_tasks도 이것을 보여줍니다. 진술 :

select session_id, wait_type, resource_address, resource_description
from sys.dm_os_waiting_tasks
where blocking_session_id is not null;

보고:

session_id | wait_type | resource_address | resource_description                                                            
----------- + ----------- + -------------------- + ----- -------------------------------------------------- --------------------------
        54 | LCK_M_X | 0x000000002a35cd40 | 키 잠금 hobtid = 72057594046054400 dbid = 6 id = lock4ed1dd780 mode = X associatedObjectId = 72057594046054400

다시 이것은 예상됩니다.

내 문제는 세션 54가 기다리는 실제 객체 이름을 찾는 방법을 알 수 없다는 것입니다.

다음 sys.dm_tran_lockssys.dm_os_waiting_tasks같은 몇 가지 쿼리를 발견했습니다 .

SELECT ....
FROM sys.dm_tran_locks AS l
  JOIN sys.dm_os_waiting_tasks AS wt ON wt.resource_address = l.lock_owner_address

그러나 위의 테스트 시나리오 에서이 조인은 아무것도 반환하지 않습니다. 따라서 해당 조인이 잘못되었거나 dm_tran_locks실제로 찾고있는 정보가 포함되어 있지 않습니다.

그래서 내가 찾고있는 것은
" 세션 54가 테이블의 잠금을 기다리고 있습니다foo " 와 같은 것을 반환하는 쿼리입니다 .


일부 배경 정보 :

내가 해결하려고하는 실제 문제는 조금 더 복잡하지만 "어떤 테이블이 세션 54를 기다리고 있는지"라는 질문으로 요약됩니다. 문제는 여러 테이블을 업데이트하는 지연 저장 프로 시저와 해당 테이블 중 일부에 액세스하는 뷰에서 선택하는 것입니다. select문은 우리가 스냅 숏 격리을 가지고 최선을 다하고 스냅 샷이 활성화 읽기에도 불구하고 차단됩니다. 선택이 차단 된 이유를 파악 하는 것 (스냅 샷 격리가 활성화 된 경우 불가능하다고 생각)은 다음 단계입니다.

첫 번째 단계로 세션이 무엇 을 기다리고 있는지 알고 싶습니다 .



@MaxVernon : 확인해 주셔서 감사합니다. 그러나 나는 더 혼란스러워합니다. 잠금 및 차단 된 세션이 있음을 알고 있는데 왜 아무것도 반환하지 않습니까?
a_horse_with_no_name 13

SQL Server 2012에서보고있는 문제를 재현 할 수 없습니다. 테스트 데이터베이스를 만들고 RCSI를 활성화하고 테이블을 만들었으며 두 업데이트 문을 모두 실행했으며 마지막 쿼리에서 행이 반환 된 것을 볼 수 있습니다.
Max Vernon

잠금을 감지하는 데 시각적 도움이 필요한 경우 SQL 잠금 파인더라는 오픈 소스 도구를 사용할 수 있습니다. 당신은에 소스 찾을 수 있습니다 github.com/LucBos/SqlLockFinder를 또는에 실행 파일을 다운로드 : sqllockfinder.com 우리가 더 잘 할 수 있도록 우리는 또한 당신이 코드를 만들 수있는 공헌을 사랑 해요.
Luc Bos

답변:


23

나는 이것이 당신이 필요로하는 것이라고 생각합니다.

USE 'yourDB'
GO
SELECT  
    OBJECT_NAME(p.[object_id]) BlockedObject
FROM    sys.dm_exec_connections AS blocking
    INNER JOIN sys.dm_exec_requests blocked
        ON blocking.session_id = blocked.blocking_session_id
    INNER JOIN sys.dm_os_waiting_tasks waitstats
        ON waitstats.session_id = blocked.session_id
    INNER JOIN sys.partitions p ON SUBSTRING(resource_description, 
        PATINDEX('%associatedObjectId%', resource_description) + 19, 
        LEN(resource_description)) = p.partition_id

3

당신은 그것을 시도 할 수 있습니다 :

SELECT 
db_name(rsc_dbid) AS 'DATABASE_NAME',
case rsc_type when 1 then 'null'
              when 2 then 'DATABASE' 
              WHEN 3 THEN 'FILE'
              WHEN 4 THEN 'INDEX'
              WHEN 5 THEN 'TABLE'
              WHEN 6 THEN 'PAGE'
              WHEN 7 THEN 'KEY'
              WHEN 8 THEN 'EXTEND'
              WHEN 9 THEN 'RID ( ROW ID)'
              WHEN 10 THEN 'APPLICATION' end  AS 'REQUEST_TYPE',

CASE req_ownertype WHEN 1 THEN 'TRANSACTION'
                   WHEN 2 THEN 'CURSOR'
                   WHEN 3 THEN 'SESSION'
                   WHEN 4 THEN 'ExSESSION' END AS 'REQUEST_OWNERTYPE',

OBJECT_NAME(rsc_objid ,rsc_dbid) AS 'OBJECT_NAME', 
PROCESS.HOSTNAME , 
PROCESS.program_name , 
PROCESS.nt_domain , 
PROCESS.nt_username , 
PROCESS.program_name ,
SQLTEXT.text 
FROM sys.syslockinfo LOCK JOIN 
     sys.sysprocesses PROCESS
  ON LOCK.req_spid = PROCESS.spid
CROSS APPLY sys.dm_exec_sql_text(PROCESS.SQL_HANDLE) SQLTEXT
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.