在阻止的流程报告中清空阻止流程


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企业版: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_cursorprepare和运行sp_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上的连接

Answers:


6

我目前无法检验该理论,但是基于发布到GitHub的最新捕获数据,我想说您<process>节点为空的原因是它需要当前正在运行的请求(许多属性在sys.dm_exec_requests而不是in sys.dm_exec_sessions),并且没有当前正在运行的请求,它无法报告任何详细信息,类似于INNER JOIN之间进行操作, sys.dm_exec_requests并且sys.dm_exec_sessions将排除会话处于活动状态但由于没有当前请求而处于空闲状态的行。

查看最上面的一组数据(monitorLoop值:1748823、1748824、1748825和1748827),我们可以看到以下内容:

  • 所述idblocked-process在每种情况下是相同的:process2552c1fc28,那就是不同的唯一属性是waittime(理解)。
  • 该属性blocking-process节点显示两者的差异lastbatchstartedlastbatchcompleted
  • 所述的属性blocking-process节点显示相同的值spid,并xactid

那么,在4个不同的查询批次中,阻塞过程的SessionID和TransactionID如何相同?轻松地,开始显式事务,然后执行这些批处理。并且由于这些是独立的批次,因此在它们之间有一定的提交时间,此时没有当前请求,因此没有要显示的过程信息(但会话和事务仍然存在)。

为了对此进行更多研究,您可以从下面的T-SQL sys.dm_exec_requests以及sys.dm_tran_locks通过将以下T-SQL放在SQL Server代理“ Transaction-SQL脚本(T-SQL)”作业步骤中,并将“数据库”设置为您正在研究的一项(在本例中是ID为6的一项),并安排此作业每10秒运行一次。下面的T-SQL将在同一数据库中创建两个表(如果它们不存在),然后,如果任何请求本身被阻塞,或者是被阻塞的Delete或Update操作,则将填充“ 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
                                     );
 */

我认为您应该可以通过打开一个查询选项卡并执行以下命令来重现此内容:

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

然后,打开第二个查询选项卡并执行以下操作:

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

PS只是说了一点,唯一没有意义的是请求和会话信息dbo.tmpBlockingResearch_Requests–仍然永远不会包含阻塞会话的行。但是我知道table变量中有阻塞的会话ID,因为它确实拉了两个SessionID的锁。这可能指向一个场景,在该场景中,在关闭来自客户端的“连接”之后,允许事务保持打开状态,但是由于连接池的缘故,该连接仍然得以保持。


@TomV我已经审阅了最新的研究数据,并拥有相当扎实的理论。我已经相应地更新了答案,包括在研究查询中添加了一部分,因此请在此处用新查询替换作业步骤SQL(我也注释掉了“锁”查询,因为我们现在确实不需要该数据了,很多数据)。我建议截断/删除现有研究表以从头开始。
所罗门·鲁兹基

@TomV好。而且我已经将repro查询更新为UPDATE而不是SELECT,因此无论如何它应该更能代表您的情况。我还在末尾添加了关于请求表中缺少行的注释。希望新的Connections表至少可以确认阻塞SessionID的继续存在。(附言,我开始清理上面的评论)。
所罗门·鲁兹基

您的工作很活跃。我需要抽出一些时间测试下一个副本,并在下周进行分析
Tom V-Monica团队

嗨,所罗门。2个新示例已发布在github上。不幸的是,使用提供的repro案例,我无法触发空的阻止进程BPR。
汤姆五世-莫妮卡团队

我没有太多时间,快速看了一下。看起来“连接”信息显示阻止会话ID仍处于活动状态,但不在会话表中。我可以稍后进行测试,但是我很确定这表明连接池(连接仍然存在)并且命令之间的连接已关闭,但事务显然已打开(因为transaction_id总是与上次看到的相同)。稍后再仔细看
。–所罗门·鲁兹基

4

由于锁升级,可能发生阻塞的事务。

Microsoft支持文章中对此进行了解释:

如何解决由SQL Server中的锁升级引起的阻塞问题

...
锁升级不会导致大多数阻塞问题。若要确定在遇到阻塞问题时是否正在发生锁定升级,请启动包含Lock:Escalation事件的SQL Profiler跟踪。如果您没有看到任何Lock:Escalation事件,则说明服务器上没有发生锁升级,并且本文中的信息不适用于您的情况。

如果正在发生锁升级,请验证已升级的表锁是否阻止了其他用户
...

检查扩展事件(物理文件),了解在阻止的进程事件之前发生的锁升级事件。

讲解

有一篇Microsoft Blog文章有更详细的说明:

SQL Server锁升级和阻止

...
步骤2:收集锁升级和阻塞的流程报告事件。

SQL Server不会自动捕获锁升级和阻塞的流程报告事件。为了知道这些事件是否正在发生,我们需要告诉SQL Server记录它们。我们的团队使用Performance Manager for Microsoft Dynamics工具来收集该信息。查看Rod Hansen的这篇文章,以获取有关该工具以及如何使用该工具收集阻止详细信息的更多信息。如果您只想使用SQL Server Profiler,则需要收集的事件如下所示:...

捕获锁升级和阻塞进程之后,必须确定锁升级是否是阻塞进程的根本原因:

...
步骤3:在SQL Server Profiler中查看跟踪。

有两个主要指标可以告诉您阻止是否与锁升级有关。

首先,您将在阻塞的流程报告事件之前看到一系列锁升级事件。下面是从Performance Analyzer for Microsoft Dynamics工具生成的跟踪中获取的示例。这是在跟踪中寻找的一件事,但这并不意味着锁升级会导致阻塞。...

并进一步

为了验证阻止实际上与锁升级有关,您需要查看被阻止的进程报告详细信息。在TextData部分中,寻找waitresource(请参见下面的屏幕截图)。如果waitresource以OBJECT开头,我们知道阻塞的语句正在等待表级锁释放,然后才能继续执行。如果waitresource以KEYPAG而不是OBJECT 开头,则该特定块中不涉及锁升级。锁定升级将始终增加对OJBECT的锁定范围,无论它从何处开始

(仅当上述匹配时)

解决方案显然是打开跟踪标志1224,这将关闭锁升级:

SQL Server锁升级和阻止

如果您同时看到这两件事,那么可以肯定地说锁升级导致了阻塞,并且您可能会从实现SQL Server跟踪标志1224中受益。

适用于Dynamics AX的SQL Server跟踪标志

跟踪标志1224根据锁的数量禁用锁升级。启用此跟踪标志可以减少由于锁升级而导致阻塞的可能性,这是我在许多AX实现中看到的。成为问题的最常见情况是当需要在一天中运行总体规划时

回答

最后,锁升级可能是进程阻塞的根本原因。


备用解决方案(流程节点为空)

在进一步研究了一些blocked_process_reports之后,可以做出以下替代解释。

扩展事件正在捕获与当前其他进程无关的blocked_process_reports。

Ergo:必须以其他原因将其屏蔽

我建议您从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将尝试在同一页上获取另一个闩锁。该第二闩锁被第一闩锁阻挡。因此,被阻止的列报告该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显示waitresource="KEY: 6:72057....。因此,这意味着此处不涉及“锁升级”。
所罗门·鲁兹基

不,您没有误读它。问题中提供的部分是此服务器上的一个问题。我的答案是针对由于阻塞和锁定升级而可能发生的问题的全局方法。如果可以解决一些主要问题(用于OBJECT级别锁定的blocked_process_reports),则较小的问题(在其他级别上的blocked_process_reports)可以解决。这就是为什么我还添加了第二个替代答案的原因。
约翰aka hot2use
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.