차단 된 프로세스 보고서에서 빈 차단 프로세스


28

확장 이벤트를 사용하여 차단 된 프로세스 보고서를 수집하고 있으며 어떤 이유로 일부 보고서에서는 blocking-process노드가 비어 있습니다. 이것은 전체 XML입니다.

<blocked-process-report monitorLoop="383674">
 <blocked-process>
  <process id="processa7bd5b868" taskpriority="0" logused="106108620" waitresource="KEY: 6:72057613454278656 (8a2f7bc2cd41)" waittime="25343" ownerId="1051989016" transactionname="user_transaction" lasttranstarted="2017-03-20T09:30:38.657" XDES="0x21f382d9c8" lockMode="X" schedulerid="7" kpid="15316" status="suspended" spid="252" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-03-20T09:39:15.853" lastbatchcompleted="2017-03-20T09:39:15.850" lastattention="1900-01-01T00:00:00.850" clientapp="Microsoft Dynamics AX" hostname="***" hostpid="1348" loginname="***" isolationlevel="read committed (2)" xactid="1051989016" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame line="1" stmtstart="40" sqlhandle="0x02000000f7def225b0edaecd8744b453ce09bdcff9b291f50000000000000000000000000000000000000000" />
    <frame line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" />
   </executionStack>
   <inputbuf>
(@P1 bigint,@P2 int)DELETE FROM DIMENSIONFOCUSUNPROCESSEDTRANSACTIONS WHERE ((PARTITION=5637144576) AND ((FOCUSDIMENSIONHIERARCHY=@P1) AND (STATE=@P2)))   </inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process />
 </blocking-process>
</blocked-process-report>

이 hobt_id가 속하는 인덱스의 인덱스 정의는 다음과 같습니다.

CREATE UNIQUE CLUSTERED INDEX [I_7402FOCUSDIMENSIONHIERARCHYIDX] ON [dbo].[DIMENSIONFOCUSUNPROCESSEDTRANSACTIONS]
(
    [PARTITION] ASC,
    [FOCUSDIMENSIONHIERARCHY] ASC,
    [STATE] ASC,
    [GENERALJOURNALENTRY] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

파티셔닝이 필요하지 않습니다. 이것은 테이블 정의입니다.

CREATE TABLE [dbo].[DIMENSIONFOCUSUNPROCESSEDTRANSACTIONS](
    [FOCUSDIMENSIONHIERARCHY] [bigint] NOT NULL DEFAULT ((0)),
    [GENERALJOURNALENTRY] [bigint] NOT NULL DEFAULT ((0)),
    [STATE] [int] NOT NULL DEFAULT ((0)),
    [RECVERSION] [int] NOT NULL DEFAULT ((1)),
    [PARTITION] [bigint] NOT NULL DEFAULT ((5637144576.)),
    [RECID] [bigint] NOT NULL,
 CONSTRAINT [I_7402RECID] PRIMARY KEY NONCLUSTERED 
(
    [RECID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[DIMENSIONFOCUSUNPROCESSEDTRANSACTIONS]  WITH CHECK ADD CHECK  (([RECID]<>(0)))
GO

전체 데이터베이스의 테이블에 정의 된 트리거 또는 외래 키가 없습니다.

정확한 SQL Server 빌드는 다음과 같습니다.

Microsoft SQL Server 2012 (SP3-CU4) (KB3165264)-11.0.6540.0 (X64)
2016 년 6 월 23 일 17:45:11 저작권 (c) Microsoft Corporation Enterprise Edition : Windows NT 6.3의 코어 기반 라이센스 (64 비트) 빌드 14393 :) (하이퍼 바이저)

확장 된 이벤트는 차단 된 프로세스 보고서를 로깅하기 만하면 매우 간단합니다.

CREATE EVENT SESSION [Dynperf_Blocking_Data] ON SERVER 
ADD EVENT sqlserver.blocked_process_report(
    ACTION(package0.collect_system_time,sqlserver.client_hostname,sqlserver.context_info)),
ADD EVENT sqlserver.lock_escalation(
    ACTION(package0.collect_system_time,sqlserver.client_hostname,sqlserver.context_info)),
ADD EVENT sqlserver.xml_deadlock_report(
    ACTION(package0.collect_system_time,sqlserver.client_hostname,sqlserver.context_info)) 
ADD TARGET package0.event_file(SET filename=N'F:\SQLTrace\Dynamics_Blocking.xel',max_file_size=(100),max_rollover_files=(10))
WITH (MAX_MEMORY=32768 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_NODE,TRACK_CAUSALITY=ON,STARTUP_STATE=ON)
GO

데이터베이스는 읽기 커밋 된 스냅 숏 격리에서 구성되며 최대 병렬 처리 수준은 1로 설정됩니다. 서버 구성은 다음과 같습니다.

+------------------------------------+-------+
|                name                | value |
+------------------------------------+-------+
| access check cache bucket count    |     0 |
| access check cache quota           |     0 |
| Ad Hoc Distributed Queries         |     0 |
| affinity I/O mask                  |     0 |
| affinity mask                      |     0 |
| affinity64 I/O mask                |     0 |
| affinity64 mask                    |     0 |
| Agent XPs                          |     1 |
| allow updates                      |     0 |
| backup compression default         |     1 |
| blocked process threshold (s)      |     2 |
| c2 audit mode                      |     0 |
| clr enabled                        |     0 |
| common criteria compliance enabled |     0 |
| contained database authentication  |     0 |
| cost threshold for parallelism     |     5 |
| cross db ownership chaining        |     0 |
| cursor threshold                   |    -1 |
| Database Mail XPs                  |     1 |
| default full-text language         |  1033 |
| default language                   |     0 |
| default trace enabled              |     1 |
| disallow results from triggers     |     0 |
| EKM provider enabled               |     0 |
| filestream access level            |     0 |
| fill factor (%)                    |     0 |
| ft crawl bandwidth (max)           |   100 |
| ft crawl bandwidth (min)           |     0 |
| ft notify bandwidth (max)          |   100 |
| ft notify bandwidth (min)          |     0 |
| index create memory (KB)           |     0 |
| in-doubt xact resolution           |     0 |
| lightweight pooling                |     0 |
| locks                              |     0 |
| max degree of parallelism          |     1 |
| max full-text crawl range          |     4 |
| max server memory (MB)             | 65536 |
| max text repl size (B)             | 65536 |
| max worker threads                 |     0 |
| media retention                    |     0 |
| min memory per query (KB)          |  1024 |
| min server memory (MB)             |     0 |
| nested triggers                    |     1 |
| network packet size (B)            |  4096 |
| Ole Automation Procedures          |     0 |
| open objects                       |     0 |
| optimize for ad hoc workloads      |     1 |
| PH timeout (s)                     |    60 |
| precompute rank                    |     0 |
| priority boost                     |     0 |
| query governor cost limit          |     0 |
| query wait (s)                     |    -1 |
| recovery interval (min)            |     0 |
| remote access                      |     1 |
| remote admin connections           |     0 |
| remote login timeout (s)           |    10 |
| remote proc trans                  |     0 |
| remote query timeout (s)           |   600 |
| Replication XPs                    |     0 |
| scan for startup procs             |     1 |
| server trigger recursion           |     1 |
| set working set size               |     0 |
| show advanced options              |     1 |
| SMO and DMO XPs                    |     1 |
| transform noise words              |     0 |
| two digit year cutoff              |  2049 |
| user connections                   |     0 |
| user options                       |     0 |
| xp_cmdshell                        |     0 |
+------------------------------------+-------+

서버 측 추적을 잠시 동안 실행했으며 확장 이벤트를 사용하는 것과 동일한 빈 노드가 추적 파일에 나타납니다.
이 차단 된 프로세스 보고서는 Dynamics AX를 실행중인 다른 서버에서 서버 쪽 추적을 사용하여 캡처되었으므로이 서버 나 빌드에만 국한되지 않습니다.

<blocked-process-report monitorLoop="1327922">
 <blocked-process>
  <process id="processbd9839848" taskpriority="0" logused="1044668" waitresource="KEY: 5:72057597098328064 (1d7966fe609a)" waittime="316928" ownerId="3415555263" transactionname="user_transaction" lasttranstarted="2017-03-27T07:59:29.290" XDES="0x1c1c0c3b0" lockMode="U" schedulerid="3" kpid="25236" status="suspended" spid="165" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-03-27T07:59:47.873" lastbatchcompleted="2017-03-27T07:59:47.873" lastattention="2017-03-27T07:58:01.490" clientapp="Microsoft Dynamics AX" hostname="***" hostpid="11072" loginname="***" isolationlevel="read committed (2)" xactid="3415555263" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame line="1" stmtstart="236" stmtend="676" sqlhandle="0x020000004d6830193d42a167edd195c201f40bb772e9ece20000000000000000000000000000000000000000"/>
   </executionStack>
   <inputbuf>
(@P1 numeric(32,16),@P2 int,@P3 bigint,@P4 nvarchar(5),@P5 nvarchar(36),@P6 int,@P7 numeric(32,16),@P8 bigint,@P9 int)UPDATE PRODCALCTRANS SET REALCOSTAMOUNT=@P1,RECVERSION=@P2 WHERE (((((((PARTITION=@P3) AND (DATAAREAID=@P4)) AND (COLLECTREFPRODID=@P5)) AND (COLLECTREFLEVEL=@P6)) AND (LINENUM=@P7)) AND (RECID=@P8)) AND (RECVERSION=@P9))   </inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process/>
 </blocking-process>
</blocked-process-report>

이 보고서에 대한 설명이 있습니까? 검색어를 차단하는 것은 무엇입니까?

잠금 장치가 오래 지나간 후 ​​보고서를 보면 어떤 일이 있었는지 알 수있는 방법이 있습니까?

추가하는 것이 유용 할 수있는 한 가지는 이러한 쿼리를 통해 실행되는 것입니다 sp_cursorpreparesp_cursorexecute

지금까지 나는 그것을 재현 할 수 없었습니다. 임의하지만 매우 자주 발생하는 것 같습니다.

Dynamics AX와 관련된 여러 인스턴스 (다른 빌드)와 여러 테이블 / 쿼리에서 발생합니다.

당시 백그라운드에서 인덱스 또는 기타 데이터베이스 유지 보수 작업이 발생하지 않습니다.

srutzky답변에 제공된 코드를 사용 하여이 차단 된 프로세스 보고서와 관련된 로깅을 캡처 할 수있었습니다.

<blocked-process-report monitorLoop="1621637">
 <blocked-process>
  <process id="processd06909c28" taskpriority="0" logused="0" waitresource="KEY: 5:72057597585719296 (d2d87c26d920)" waittime="78785" ownerId="4436575948" transactionname="user_transaction" lasttranstarted="2017-04-13T07:39:17.590" XDES="0x3219d034e0" lockMode="U" schedulerid="3" kpid="133792" status="suspended" spid="106" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-04-13T07:39:17.657" lastbatchcompleted="2017-04-13T07:39:17.657" lastattention="1900-01-01T00:00:00.657" clientapp="Microsoft Dynamics AX" hostname="****" hostpid="11800" loginname="****" isolationlevel="read committed (2)" xactid="4436575948" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame line="1" stmtstart="72" stmtend="256" sqlhandle="0x0200000076a6a92ab1256af09321b056ab243f187342f9960000000000000000000000000000000000000000"/>
    <frame line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"/>
   </executionStack>
   <inputbuf>
(@P1 int,@P2 int,@P3 bigint,@P4 int)UPDATE PRODROUTEJOB SET JOBSTATUS=@P1,RECVERSION=@P2 WHERE ((RECID=@P3) AND (RECVERSION=@P4))   </inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process/>
 </blocking-process>
</blocked-process-report>

이것은 같은 시간에 같은 리소스에 대한 로깅 테이블에서 찾을 수 있습니다. 문자 제한으로 인한 요점

추가 조사에 따르면 차단 프로세스가 비어있는 보고서 바로 전후에 차단 프로세스 노드가있는 동일한 resourceid에 대한 보고서가 있습니다.

<blocked-process-report monitorLoop="1621636">
 <blocked-process>
  <process id="processd06909c28" taskpriority="0" logused="0" waitresource="KEY: 5:72057597585719296 (d2d87c26d920)" waittime="73765" ownerId="4436575948" transactionname="user_transaction" lasttranstarted="2017-04-13T07:39:17.590" XDES="0x3219d034e0" lockMode="U" schedulerid="3" kpid="133792" status="suspended" spid="106" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-04-13T07:39:17.657" lastbatchcompleted="2017-04-13T07:39:17.657" lastattention="1900-01-01T00:00:00.657" clientapp="Microsoft Dynamics AX" hostname="***" hostpid="11800" loginname="***" isolationlevel="read committed (2)" xactid="4436575948" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame line="1" stmtstart="72" stmtend="256" sqlhandle="0x0200000076a6a92ab1256af09321b056ab243f187342f9960000000000000000000000000000000000000000"/>
    <frame line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"/>
   </executionStack>
   <inputbuf>
(@P1 int,@P2 int,@P3 bigint,@P4 int)UPDATE PRODROUTEJOB SET JOBSTATUS=@P1,RECVERSION=@P2 WHERE ((RECID=@P3) AND (RECVERSION=@P4))   </inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process status="sleeping" spid="105" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2017-04-13T07:40:31.417" lastbatchcompleted="2017-04-13T07:40:31.423" lastattention="1900-01-01T00:00:00.423" clientapp="Microsoft Dynamics AX" hostname="**" hostpid="11800" loginname="**" isolationlevel="read committed (2)" xactid="4436165115" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack/>
   <inputbuf>
(@P1 bigint,@P2 nvarchar(5),@P3 bigint,@P4 bigint,@P5 nvarchar(11),@P6 int,@P7 nvarchar(21),@P8 datetime2)SELECT T1.REGDATETIME,T1.REGDATETIMETZID,T1.WORKERPILOT,T1.WORKER,T1.WRKCTRIDPILOT,T1.REGTYPE,T1.PROFILEDATE,T1.JOBID,T1.JOBIDABS,T1.MATCHRECIDSTARTSTOP,T1.JOBACTIVE,T1.RESNO,T1.STARTITEMS,T1.GOODITEMS,T1.SCRAPITEMS,T1.FINISHEDCODE,T1.TMPGOODITEMS,T1.TMPSCRAPITEMS,T1.SYSMRPUPDATEREQUEST,T1.ERROR,T1.ERRORTXT,T1.TMPSTARTITEMS,T1.AUTOSTAMP,T1.ERRORSPECIFICATION,T1.COSTCATEGORY,T1.ONCALLACTIVITY,T1.TERMINALID,T1.PDSCWGOODITEMS,T1.PDSCWSCRAPITEMS,T1.PDSCWSTARTITEMS,T1.RETAILTERMINALID,T1.MODIFIEDDATETIME,T1.RECVERSION,T1.PARTITION,T1.RECID FROM JMGTERMREG T1 WHERE (((PARTITION=@P1) AND (DATAAREAID=@P2)) AND (((((WORKER=@P3) OR ((WORKER=@P4) AND (WRKCTRIDPILOT=@P5))) AND (REGTYPE=@P6)) AND (JOBID=@P7)) AND (REGDATETIME&gt;=@P8))) ORDER BY T1.REGDATETIME   </inputbuf>
  </process>
 </blocking-process>
</blocked-process-report>

srutzky가 제공 한 새 스크립트를 사용하여 새 데이터를 수집했습니다. 최대 게시물 길이 때문에 github에 게시됩니다 .

원래 게시 된 데이터에 세션 ID가 모두 없기 때문에 일부 새 데이터가 게시되었습니다. github에 다시

github 의 연결 포함한 새로운 데이터

답변:


6

현재이 이론을 테스트 할 수는 없지만 GitHub에 게시 된 가장 최근의 캡처 데이터를 기반으로 <process>노드가 비어 있는 이유 는 현재 실행중인 요청이 필요하기 때문입니다 (다수의 속성은 sys.dm_exec_requests하지에 sys.dm_exec_sessions) 및 현재 실행중인 요청없이, 그것은 어떻게 일을 유사 모든 세부 사항을보고 할 수 없습니다 INNER JOIN사이 sys.dm_exec_requestssys.dm_exec_sessions 세션이 활성화되어 있지만 현재 요청에 의한 유휴 상태 인 경우 행을 제외합니다.

최상위 데이터 세트 ( monitorLoop값 : 1748823, 1748824, 1748825 및 1748827)를 보면 다음을 볼 수 있습니다.

  • id의는 blocked-process각각의 경우에서 동일하다 : process2552c1fc28 과 상이한 유일한 특성은 인 waittime(당연).
  • 의 속성 blocking-process노드가 둘의 차이를 보여 lastbatchstartedlastbatchcompleted
  • blocking-process노드 의 속성은 spidxactid

그렇다면 블로킹 프로세스의 SessionID와 TransactionID는 4 가지 쿼리 배치에서 어떻게 동일 할 수 있습니까? 쉬운 트랜잭션이 시작된 다음 이러한 일괄 처리가 실행되었습니다. 이들은 개별 배치이기 때문에 제출 사이에 시간이 있으므로 현재 요청이 없으므로 프로세스 정보가 표시되지 않습니다 (그러나 세션과 트랜잭션은 여전히 ​​존재합니다).

이것으로 추가 연구를하기 위해, 당신은에서 도움이되는 정보를 캡처 할 수 있습니다 sys.dm_exec_requestssys.dm_tran_locks"데이터베이스"를 할 수있는 설정, SQL Server 에이전트 "트랜잭션-SQL 스크립트 (T-SQL)"작업 단계에서 다음 T-SQL을 배치하여을 하나는 연구 중이며 (이 경우 ID가 6 인) 10 초마다 실행되도록이 작업을 예약합니다. 아래의 T-SQL은 동일한 DB에 존재하지 않는 두 개의 테이블을 만든 다음 요청이 자체를 차단하거나 차단 또는 삭제 작업 인 경우 "요청"테이블을 채 웁니다. . 요청이 있으면 캡처를 시도합니다.

  • 차단 프로세스에 대한 세션 및 요청 정보 (이 부분은 활성 요청이 있다고 가정하지 않으므로 RIGHT JOIN최소한 세션 정보를 가져옵니다)
  • 차단 및 (바람직하게) 차단 프로세스에 대한 연결 정보.
  • 그 같은 SESSION_ID의 (단지 잠금 정보가되지 않는다는 것을 명심 현재 잠금 을 보장 할만큼 자주 여전히 정보가 충분히 좋은, 즉 정보가 실행이 두 문장 사이의 시간에 변경할 수 있습니다으로 100 % 정확 캡처 가치)). 이 섹션은 현재 주석 처리되어 있습니다.

SQL Server 에이전트 T-SQL 작업 단계 :

-- !! Remember to set the "Database" for the T-SQL Job Step to
--    the DB that has database_id = 6 !!
SET NOCOUNT ON;
IF (OBJECT_ID(N'dbo.tmpBlockingResearch_Requests') IS NULL)
BEGIN
  -- Create requests capture table
  SELECT SYSDATETIME() AS [CaptureTime], req.*,
         ses.login_time, ses.[host_name], ses.[program_name], ses.host_process_id,
         ses.client_version, ses.client_interface_name, ses.security_id,
         ses.login_name, ses.nt_domain, ses.nt_user_name, ses.memory_usage,
         ses.total_scheduled_time, ses.endpoint_id, ses.last_request_start_time,
         ses.last_request_end_time, ses.is_user_process, ses.original_security_id,
         ses.original_login_name, ses.last_successful_logon, ses.last_unsuccessful_logon,
         ses.unsuccessful_logons, ses.authenticating_database_id
  INTO   dbo.tmpBlockingResearch_Requests
  FROM   sys.dm_exec_requests req
  INNER JOIN sys.dm_exec_sessions ses
          ON ses.[session_id] = req.[session_id]
  WHERE  1 = 0;
END;

IF (OBJECT_ID(N'dbo.tmpBlockingResearch_Connections') IS NULL)
BEGIN
  -- Create connections capture table
  SELECT SYSDATETIME() AS [CaptureTime], con.*
  INTO   dbo.tmpBlockingResearch_Connections
  FROM   sys.dm_exec_connections con
  WHERE  1 = 0;
END;

IF (OBJECT_ID(N'dbo.tmpBlockingResearch_Locks') IS NULL)
BEGIN
  -- Create locks capture table
  SELECT SYSDATETIME() AS [CaptureTime], loc.*
  INTO   dbo.tmpBlockingResearch_Locks
  FROM   sys.dm_tran_locks loc
  WHERE  1 = 0;
END;
---------------------------------
DECLARE @SessionIDs TABLE (SessionID SMALLINT NOT NULL,
                           BlockingSessionID SMALLINT NOT NULL);

INSERT INTO dbo.tmpBlockingResearch_Requests
OUTPUT inserted.[session_id], inserted.[blocking_session_id]
INTO   @SessionIDs ([SessionID], [BlockingSessionID])
  SELECT SYSDATETIME() AS [CaptureTime], req.*,
         ses.login_time, ses.[host_name], ses.[program_name], ses.host_process_id,
         ses.client_version, ses.client_interface_name, ses.security_id,
         ses.login_name, ses.nt_domain, ses.nt_user_name, ses.memory_usage,
         ses.total_scheduled_time, ses.endpoint_id, ses.last_request_start_time,
         ses.last_request_end_time, ses.is_user_process, ses.original_security_id,
         ses.original_login_name, ses.last_successful_logon, ses.last_unsuccessful_logon,
         ses.unsuccessful_logons, ses.authenticating_database_id
  FROM   sys.dm_exec_requests req
  INNER JOIN sys.dm_exec_sessions ses
          ON ses.[session_id] = req.[session_id]
  WHERE ses.[is_user_process] = 1
  AND   req.[database_id] = DB_ID()
  AND   (
          req.blocking_session_id IN (req.[session_id], -2, -3, -4)
    OR   (req.[command] IN (N'DELETE', N'UPDATE') AND req.[blocking_session_id] > 0)
        );

-- Get at least session info, if not also request info, on blocking process
INSERT INTO dbo.tmpBlockingResearch_Requests
  SELECT SYSDATETIME() AS [CaptureTime], req.*,
         ses.login_time, ses.[host_name], ses.[program_name], ses.host_process_id,
         ses.client_version, ses.client_interface_name, ses.security_id,
         ses.login_name, ses.nt_domain, ses.nt_user_name, ses.memory_usage,
         ses.total_scheduled_time, ses.endpoint_id, ses.last_request_start_time,
         ses.last_request_end_time, ses.is_user_process, ses.original_security_id,
         ses.original_login_name, ses.last_successful_logon, ses.last_unsuccessful_logon,
         ses.unsuccessful_logons, ses.authenticating_database_id
  FROM   sys.dm_exec_requests req
  RIGHT JOIN sys.dm_exec_sessions ses
          ON ses.[session_id] = req.[session_id]
  WHERE ses.[session_id] IN (SELECT DISTINCT [BlockingSessionID] FROM @SessionIDs);

-- If any rows are captured this time, try to capture their connection info
INSERT INTO dbo.tmpBlockingResearch_Connections
  SELECT SYSDATETIME() AS [CaptureTime], con.*
  FROM   sys.dm_exec_connections con
  WHERE  con.[session_id] IN (
                              SELECT [SessionID]
                              FROM @SessionIDs
                              UNION -- No "ALL" so it does DISTINCT
                              SELECT [BlockingSessionID]
                              FROM @SessionIDs
                             );

/*
-- If any rows are captured this time, try to capture their lock info
INSERT INTO dbo.tmpBlockingResearch_Locks
  SELECT SYSDATETIME() AS [CaptureTime], loc.*
  FROM   sys.dm_tran_locks loc
  WHERE  loc.[request_session_id] IN (
                                      SELECT [SessionID]
                                      FROM @SessionIDs
                                      UNION -- No "ALL" so it does DISTINCT
                                      SELECT [BlockingSessionID]
                                      FROM @SessionIDs
                                     );
 */

하나의 쿼리 탭을 열고 다음을 실행하여 이것을 재현 할 수 있어야한다고 생각합니다.

CREATE TABLE dbo.tmp (Col1 INT);
BEGIN TRAN;
INSERT INTO dbo.tmp (Col1) VALUES (1);

그런 다음 두 번째 쿼리 탭을 열고 다음을 실행하십시오.

UPDATE dbo.tmp
SET    Col1 = 2
WHERE  Col1 = 1;

추신 : 그것은 말이 되겠지만, 이해가되지 않는 유일한 것은 요청 및 세션 정보 – dbo.tmpBlockingResearch_Requests– 여전히 블로킹 세션에 대한 행을 포함하지 않는다는 것입니다. 그러나 테이블 변수가 두 SessionID에 대한 잠금을 풀 때 차단 세션 ID가 있음을 알고 있습니다. 이는 클라이언트의 "연결"이 닫힌 후에도 트랜잭션이 열린 상태로 유지되지만 연결 풀링으로 인해 연결이 계속 유지되는 시나리오를 가리킬 수 있습니다.


@TomV 나는 최신 연구 데이터를 검토했으며 꽤 견고한 이론을 가지고 있습니다. 리서치 쿼리에 섹션 추가를 포함하여 적절하게 내 답변을 업데이트 했으므로 작업 단계 SQL을 새 쿼리로 바꾸십시오 (지금은 데이터가 실제로 필요하지 않기 때문에 "잠금"쿼리도 주석 처리했습니다) 많은 데이터입니다). 기존 연구 테이블을 자르거나 삭제하여 처음부터 다시 시작하는 것이 좋습니다.
Solomon Rutzky 2016 년

@TomV Ok. 그리고 내 repro 쿼리를 SELECT 대신 UPDATE로 업데이트 했으므로 어쨌든 상황을보다 잘 대표해야합니다. 또한 요청 테이블에 누락 된 행에 대한 메모를 추가했습니다. 새 Connections 테이블이 차단 SessionID가 계속 존재하는지 확인하기를 바랍니다. (PS, 위의 의견을 정리하기 시작했습니다).
Solomon Rutzky 2016 년

귀하의 직업이 활성화되었습니다. 다음 주에 재현을 테스트하고 분석 할 시간을 찾아야합니다.
Tom V-Team Monica

안녕 솔로몬. github에 2 개의 새로운 예제가 게시되었습니다. 불행히도 제공된 재현 사례를 사용하여 빈 차단 프로세스 BPR을 트리거 할 수 없습니다.
Tom V-팀 모니카

시간이 없어서 아주 빨리 보았습니다. 연결 정보에 차단 세션 ID가 여전히 활성 상태이지만 세션 테이블에는없는 것으로 보입니다. 나중에 이것을 테스트 할 수는 있지만 연결 풀링 (연결이 여전히 존재 함)을 나타내며 명령 사이의 연결이 닫히지 만 트랜잭션이 명확하게 열립니다 (transaction_id는 항상 지난번에 보았으므로). 나중에 자세히 살펴 보겠습니다 ..
Solomon Rutzky

4

잠금 에스컬레이션으로 인해 차단 된 트랜잭션이 발생할 수 있습니다.

이 내용은 Microsoft 지원 문서에서 설명합니다.

SQL Server에서 잠금 에스컬레이션으로 인한 차단 문제를 해결하는 방법

...
잠금 에스컬레이션으로 인해 대부분의 차단 문제가 발생하지 않습니다. 차단 문제가 발생하는 시간에 잠금 에스컬레이션이 발생하는지 확인하려면 Lock : Escalation 이벤트가 포함 된 SQL 프로파일 러 추적을 시작하십시오. Lock : Escalation 이벤트가 표시되지 않으면 서버에서 잠금 에스컬레이션이 발생하지 않으며이 문서의 정보가 현재 상황에 적용되지 않습니다.

잠금 에스컬레이션이 발생하면 에스컬레이션 된 테이블 잠금이 다른 사용자를 차단하는지 확인하십시오
.

차단 된 프로세스 이벤트 전에 발생한 잠금 에스컬레이션 이벤트에 대해서는 확장 이벤트 (실제 파일)를 확인하십시오 .

설명

자세한 내용을 다루는 Microsoft 블로그 기사가 있습니다.

SQL Server 잠금 에스컬레이션 및 차단

...
2 단계 : 잠금 에스컬레이션 및 차단 된 프로세스 보고서 이벤트 수집

잠금 에스컬레이션 및 차단 된 프로세스 보고서 이벤트는 SQL Server에 의해 자동으로 캡처되지 않습니다. 이러한 이벤트가 발생하는지 확인하려면 SQL Server에 이벤트를 기록하도록 지시해야합니다. 우리 팀은 Microsoft Dynamics 용 성능 분석기 도구를 사용하여 해당 정보를 수집합니다. 툴에 대한 자세한 정보와 툴을 사용하여 차단 세부 정보를 수집하는 방법에 대한 자세한 내용은 Rod Hansen의이 게시물을 확인하십시오. SQL Server 프로파일 러를 사용하려는 경우 수집해야 할 이벤트는 다음과 같습니다. ...

잠금 에스컬레이션 및 차단 된 프로세스를 캡처 한 후에는 잠금 에스컬레이션이 차단 된 프로세스의 근본 원인인지 판별해야합니다.

...
3 단계 : SQL Server 프로파일 러에서 추적을 검토합니다.

차단이 잠금 에스컬레이션과 관련이 있는지 알려주는 두 가지 주요 표시기가 있습니다.

먼저 차단 된 프로세스 보고서 이벤트 바로 앞에 일련의 잠금 에스컬레이션 이벤트가 표시됩니다. 아래는 Microsoft Dynamics 도구 용 성능 분석기에서 생성 된 추적에서 가져온 예입니다. 이것은 추적에서 찾아야 할 사항이지만 이것이 잠금 에스컬레이션으로 인해 차단을 의미하는 것은 아닙니다. ...

그리고 더

차단이 실제로 잠금 에스컬레이션과 관련되어 있는지 확인하려면 차단 된 프로세스 보고서 세부 사항을 확인해야합니다. TextData 섹션에서 waitresource를 찾으십시오 (아래 스크린 샷 참조). waitresource가 OBJECT로 시작하면 차단 된 명령문이 테이블 레벨 잠금이 해제되기 전에 대기 중임을 알 수 있습니다. waitresource가 OBJECT 대신 KEY 또는 PAG로 시작하면 잠금 에스컬레이션이 해당 특정 블록에 포함되지 않습니다 . 잠금 에스컬레이션은 시작 위치에 관계없이 항상 OJBECT에 대한 잠금 범위를 증가시킵니다.

해결책

(위에서 언급 한 경우에만)

해결 방법은 잠금 에스컬레이션을 해제하는 추적 플래그 1224를 켜는 것 같습니다.

SQL Server 잠금 에스컬레이션 및 차단

이 두 가지를 함께 보면 잠금 에스컬레이션으로 인해 차단이 발생하고 SQL Server 추적 플래그 1224를 구현하면 도움이 될 것입니다.

Dynamics AX에 대한 SQL Server 추적 플래그

추적 플래그 1224는 잠금 수에 따라 잠금 에스컬레이션을 비활성화합니다. 이 추적 플래그를 활성화하면 잠금 에스컬레이션으로 인한 블로킹 가능성을 줄일 수 있습니다. 수많은 AX 구현에서 본 것입니다. 이것이 가장 문제가되는 가장 일반적인 시나리오는 낮에 마스터 계획을 실행해야하는 경우입니다.

대답

결국 잠금 에스컬레이션이 차단 된 프로세스의 근본 원인 일 수 있습니다.


대체 솔루션 (프로세스 노드가 비어 있음)

block_process_reports에 대한 추가 조사 후 다음과 같은 대체 설명이 가능합니다.

확장 이벤트가 당시 다른 프로세스와 관련이없는 block_process_reports를 캡처 중입니다.

Ergo : 다른 이유로 차단되어야합니다

SQL Server의 sys.dm_os_wait_stats보기에서 대기 유형의 시간 프레임을 캡처하고 측정하는 동안 발생하는 blocks_process_reports와 숫자를 상관시키는 것이 좋습니다. 폴 랜달 좋은 스크립트를 가지고 나에게 대기 통계 보내기 내 조언과 리턴 무료 인 Pluralsight 30 일을 얻을

이 스크립트는 현재 카운터를 캡처하고 23 시간 동안 대기 (수정 가능)하고 현재 카운터를 다시 캡처 한 후 비교하여 대기 유형의 상위 95 %를 제공합니다. 이것을 1 시간 동안 시도하고 XEL 파일을 편리하게 사용할 수 있습니다.

스토리지의 쓰기 속도가 느리다는 대기 유형 (예 : LCK_M_SH,…)을 찾을 수 있습니다. 또는 다른 오버 헤드가 있습니다 (예 : CX_PACKET_WAITS,….). 업데이트 속도가 느려집니다. 그런 다음 sys.dm_os_wait_stats가 빈 노드가있는 blocking_process_reports와 관련되어 있는지 확인할 수 있습니다.

차단 된 SPID가 동일한 SPID에 의해 차단되는 경우가 있습니다.

sysprocesses 테이블의 차단 된 열은 SQL Server 2000 SP4를 설치 한 후 래치 대기를 위해 채워집니다.

SPID가 I / O 페이지 래치를 기다리는 중이면 차단 된 열이 SPID 자체를 차단하고 있음을 간단히보고하는 것을 알 수 있습니다. 이 동작은 데이터 페이지에서 I / O 작업에 래치가 사용되는 방식의 부작용입니다. 스레드가 I / O 요청을 발행하면 I / O 요청을 발행하는 SPID가 페이지에서 래치를 획득합니다. 모든 SQL Server 2000 I / O 작업은 비동기식입니다. 따라서 SPID는 I / O 요청을 발행 한 SPID가 요청이 완료되기를 기다려야하는 경우 동일한 페이지에서 다른 래치를 확보하려고 시도합니다. 이 두 번째 래치는 첫 번째 래치에 의해 차단됩니다. 따라서 차단 된 열은 SPID 자체를 차단하고 있다고보고합니다. I / O 요청이 완료되면 첫 번째 래치가 해제됩니다. 그런 다음 두 번째 래치 요청이 승인됩니다.

다른 답변

이는 IO 문제가있을 수 있다는 추가 표시입니다. 이러한 문제로 인해 "차단 된 프로세스"가 발생하지만 관련 외부 SPID가 없습니다. 확장 이벤트는 프로세스 / SPID를 별도의 노드에보고하지 않을 수 있습니다.


이 내용을 잘못 읽었을 수 있지만이 정보가 문제가 잠금 에스컬레이션 이 아님을 증명 하지 않습니까? 인용 된 한 섹션은라고 말하며 "look at the blocked process report details."질문에서 최상위 XML은 차단 된 프로세스 보고서입니다. 다음으로 인용 된 동일한 섹션에 "If waitresource starts with KEY or PAG instead of OBJECT, then lock escalation isn’t involved in that specific block."``blocked-process-report-XML XML shows ''가 표시 waitresource="KEY: 6:72057....됩니다. 따라서 여기서는 "잠금 에스컬레이션이 포함되지 않습니다"라는 의미입니다.
Solomon Rutzky

아니요, 당신은 이것을 잘못 읽고 있지 않습니다. 질문에 제공된 섹션은이 서버에서 한 가지 문제입니다. 내 대답은 차단 및 잠금 에스컬레이션으로 인해 발생할 수있는 문제에 대한 글로벌 접근 방식입니다. 일부 주요 문제 (OBJECT 레벨 잠금의 경우 blocked_process_reports)를 수정할 수 있으면 작은 문제 (다른 레벨의 blocked_process_reports)가 스스로 해결 될 수 있습니다. 이것이 두 번째 대체 답변을 추가 한 이유입니다.
John aka hot2use
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.