ブロックされたプロセスレポートの空のブロックプロセス


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 Copyright(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

データベースはRead Committed Snapshot Isolationで構成され、最大並列度は 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>

これは、その頃の同じリソースのロギングテーブルにあります。文字数制限のための要点

さらなる調査により、空のブロックプロセスがあるレポートの直前と直後に、ブロックプロセスノードを持つ同じリソースIDのレポートがあることがわかります。

<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_requestssys.dm_exec_sessionsなく、現在実行中のリクエストがない場合、詳細をレポートできません。INNER JOINsys.dm_exec_requestsを行う方法と同様sys.dm_exec_sessionsに、現在のリクエストがないためセッションがアクティブであるがアイドル状態の行を除外します。

データの最上部セット(monitorLoop値:1748823、1748824、1748825、および1748827)を見ると、次のことがわかります。

  • idのは、blocked-processそれぞれの場合に同じである:process2552c1fc28、及び異なる唯一の属性であるwaittime(当然のこと)。
  • blocking-processノードの属性は両方の違いを示しlastbatchstartedlastbatchcompleted
  • blocking-processノードの属性は、spidおよびxactid

では、ブロックプロセスのSessionIDとTransactionIDを4つの異なるクエリバッチでどのように同じにすることができますか?簡単に、明示的なトランザクションが開始され、これらのバッチが実行されました。また、これらは個別のバッチであるため、送信されるまでに時間があり、その時点で現在の要求はなく、したがって、表示するプロセス情報はありません(ただし、セッションとトランザクションはまだあります)。

この中に追加の調査を行うためには、あなたがから役立つ情報をキャプチャすることができますsys.dm_exec_requestsし、sys.dm_tran_locksSQL Serverエージェント「トランザクション-SQLスクリプト(T-SQL)」ジョブステップで次のT-SQLを配置することによって、あることを「データベース」を設定します調査中(この場合はIDが6のジョブ)で、このジョブを10秒ごとに実行するようにスケジュールします。以下のT-SQLは、同じDBに2つのテーブルが存在しない場合は作成し、リクエストがそれ自体をブロックしている場合、または削除または更新操作がブロックされている場合、「Requests」テーブルに入力します。リクエストが見つかった場合、キャプチャを試みます:

  • ブロッキングプロセスのセッションおよびリクエスト情報(この部分は、アクティブなリクエストがあることを前提としていないため、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
                                     );
 */

1つのクエリタブを開き、次を実行することでこれを再現できるはずです。

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

次に、2番目のクエリタブを開き、次を実行します。

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

PS言っておくと、意味をなさない唯一のことは、リクエストとセッション情報dbo.tmpBlockingResearch_Requestsにブロックセッションの行が含まれていないことです。それでも、テーブル変数には、両方のSessionIDのロックを取得したため、ブロッキングセッションIDが含まれていることがわかります。これは、クライアントからの「接続」が閉じられた後、トランザクションが開いたままになることを許可されているが、接続プーリングにより接続が維持されているシナリオを指している可能性があります。


@TomV最新の研究データをレビューし、かなり堅実な理論を持っています。研究クエリにセクションを追加するなど、それに応じて回答を更新しましたので、ここでジョブステップSQLを新しいクエリに置き換えてください(「ロック」クエリもコメントアウトしました。大量のデータです)。既存の調査テーブルを切り捨て/ドロップして、最初からやり直すことをお勧めします。
ソロモンラツキー

@TomV OK。そして、reproクエリをSELECTではなくUPDATEに更新しましたので、とにかくあなたの状況をよりよく表すべきです。最後に、requestsテーブルの行が欠落しているというメモも追加しました。願わくば、新しいConnectionsテーブルが少なくともブロッキングセッションIDの存在の継続を確認することを願っています。(PS、私は上記のコメントを整理し始めました)。
ソロモンラッツキー

ジョブはアクティブです。再現性をテストし、来週分析する時間を見つける必要があります
トムV-チームモニカ

こんにちは、ソロモン。2つの新しい例がgithubに投稿されました。残念ながら、提供されている再現ケースを使用して空のブロックプロセスBPRをトリガーすることはできませんでした。
トムV-チームモニカ

あまり時間がないので、非常に簡単に見てみました。接続情報には、ブロッキングセッションIDがまだアクティブになっているように見えますが、セッションテーブルにはありません。これは後でテストできますが、接続プーリング(接続はまだある)とコマンド間で接続が閉じられているが、トランザクションが明確に開いていることを示しています(transaction_idは常に前回と同じなので)。...後で詳しく見てみましょう
ソロモンRutzky

4

ロックのエスカレーションが原因で、ブロックされたトランザクションが発生する可能性があります。

これは、Microsoftサポート記事で説明されています。

SQL Serverのロックエスカレーションによって引き起こされるブロッキングの問題を解決する方法

...
ロックのエスカレーションは、ほとんどのブロッキングの問題を引き起こしません。ブロックの問題が発生する前後にロックエスカレーションが発生しているかどうかを判断するには、Lock:Escalationイベントを含むSQLプロファイラートレースを開始します。Lock:Escalationイベントが表示されない場合、サーバーでロックのエスカレーションが発生していないため、この記事の情報は状況に当てはまりません。

ロックのエスカレーションが発生している場合、エスカレーションされたテーブルロックが他のユーザーをブロックしていることを確認してください
...

ブロックされたプロセスイベントの前に発生したロックエスカレーションイベントの拡張イベント(物理ファイル)を確認します。

説明する

詳細については、Microsoftブログの記事をご覧ください。

SQL Serverロックのエスカレーションとブロック

...
ステップ2:ロックエスカレーションとブロックされたプロセスのレポートイベントを収集します。

ロックエスカレーションとブロックされたプロセスレポートイベントは、SQL Serverによって自動的にキャプチャされません。これらのイベントが発生しているかどうかを知るために、それらを記録するようにSQL Serverに指示する必要があります。私たちのチームは、Microsoft Dynamicsツールのパフォーマンスアナライザーを使用して、その情報を収集します。このツールの詳細とブロッキングの詳細を収集する方法については、Rod Hansenによるこの投稿をご覧ください。SQL Server Profilerを使用する場合、収集する必要があるイベントを以下に示します。

ロックエスカレーションとブロックされたプロセスをキャプチャしたら、ロックエスカレーションがブロックされたプロセスの根本的な原因であるかどうかを判断する必要があります。

...
ステップ3:SQL Server Profilerでトレースを確認します。

ブロックがロックエスカレーションに関連しているかどうかを示す2つの主要なインジケータがあります。

最初に、ブロックされたプロセスレポートイベントの直前に一連のロックエスカレーションイベントが表示されます。以下は、Performance Analyzer for Microsoft Dynamicsツールによって生成されたトレースからの例です。これはトレースで探すべきことの1つですが、これだけでは、ロックのエスカレーションがブロッキングを引き起こしているという意味ではありません。...

そしてさらに

ブロックがロックエスカレーションに実際に関連していることを確認するには、ブロックされたプロセスレポートの詳細を確認する必要があります。TextDataセクションで、waitresourceを探します(下のスクリーンショットを参照)。waitresourceがOBJECTで始まる場合、ブロックされたステートメントは、続行する前にテーブルレベルのロックが解放されるのを待っていることがわかります。waitresourceがOBJECTの代わりにKEYまたはPAGで始まる場合、ロックエスカレーションはその特定のブロックに関与しません。ロックのエスカレーションは、開始場所に関係なく、ロックの範囲を常にOJBECTに増やします

溶液

(上記の条件が一致する場合のみ)

解決策は、ロックエスカレーションをオフにするトレースフラグ1224をオンにすることです。

SQL Serverロックのエスカレーションとブロック

これら2つのことを一緒に見ると、ロックのエスカレーションがブロッキングを引き起こしている可能性が高く、SQL Serverトレースフラグ1224を実装することでメリットが得られるでしょう。

Dynamics AXのSQL Serverトレースフラグ

トレースフラグ1224は、ロックの数に基づいてロックエスカレーションを無効にします。このトレースフラグを有効にすると、ロックのエスカレーションによるブロックの可能性を減らすことができます。これは、多くのAX実装で見たものです。これが問題となる最も一般的なシナリオは、マスタープランニングを1日中に実行する必要がある場合です。

回答

最終的に、ロックのエスカレーションがブロックされたプロセスの根本原因である可能性があります。


代替ソリューション(プロセスノードが空)

いくつかのblocked_process_reportsをさらに調査した後、次の代替説明を作成できます。

拡張イベントは、その時点で他のプロセスとは無関係なblocked_process_reportsをキャプチャしています。

エルゴ:別の理由でブロックする必要があります

SQL Serverのsys.dm_os_wait_statsビューから待機タイプのタイムフレームをキャプチャし、測定中に発生したblocked_process_reportsと数値を相関させることをお勧めします。Paul Randallには良いスクリプトがあり ます。待機統計を送信して、アドバイスと30日間の無料Pluralsightを受け取りましょう

スクリプトは現在のカウンターをキャプチャし、23時間待機し(変更可能)、現在のカウンターを再キャプチャし、それらを比較して待機タイプの上位95%を提供します。これを1時間ほど試して、XELファイルを手元に置いておくことができます。

ストレージの書き込みが遅いことを示す待機タイプ(LCK_M_SHなど)が見つかる場合があります。または、他のオーバーヘッド(CX_PACKET_WAITSなど)があること。何かがアップデートを遅くしています。これにより、sys.dm_os_wait_statsが空のノードを使用するblocked_process_reportsに関連しているかどうかを確認できます。

ブロックされたSPIDが同じSPIDによってブロックされている場合があります。

SQL Server 2000 SP4をインストールした後、sysprocessesテーブルのブロックされた列にラッチ待機が設定されます

SPIDがI / Oページラッチを待機しているとき、ブロックされた列がSPIDが自身をブロックしていることを簡単に報告することがあります。この動作は、ラッチがデータページのI / O操作に使用される方法の副作用です。スレッドがI / O要求を発行すると、I / O要求を発行するSPIDはページのラッチを取得します。SQL Server 2000のすべてのI / O操作は非同期です。したがって、I / O要求を発行したSPIDが要求の終了を待つ必要がある場合、SPIDは同じページで別のラッチを取得しようとします。この2番目のラッチは、最初のラッチによってブロックされます。したがって、ブロックされた列は、SPIDがそれ自体をブロックしていることを報告します。I / O要求が終了すると、最初のラッチが解放されます。次に、2番目のラッチ要求が許可されます。

別の回答

これは、IOの問題が発生している可能性があることをさらに示しています。これらの問題により、「ブロックされたプロセス」が発生しますが、関連する外部SPIDはありません。拡張イベントは、別のノードでプロセス/ SPIDを報​​告しない場合があります。


私はこれを誤解している可能性がありますが、この情報は問題がロックエスカレーションではないことを証明していませんか?引用されたセクションの1つ"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が表示されますwaitresource="KEY: 6:72057....。つまり、ここでは「ロックエスカレーションは関係ありません」ということです。
ソロモンラッツキー

いいえ、あなたはこれを誤解していません。質問で提供されているセクションは、このサーバーの1つの問題です。私の答えは、ブロッキングとロックエスカレーションが原因で発生する可能性のある問題に対するグローバルなアプローチです。いくつかの主要な問題(OBJECTレベルのロックのblocked_process_reports)を修正できる場合、小さな問題(他のレベルのblocked_process_reports)が解決する可能性があります。これが、2番目の代替回答も追加した理由です。
ジョン別名hot2use
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.