Quy trình chặn trống trong báo cáo quy trình bị chặn


28

Tôi đang thu thập các báo cáo quá trình bị chặn bằng cách sử dụng Sự kiện mở rộng và vì một số lý do trong một số báo cáo, blocking-processnút này trống. Đây là xml đầy đủ:

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

Định nghĩa chỉ mục cho chỉ mục mà hobt_id này thuộc về là

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

Không có phân vùng liên quan, đây là định nghĩa bảng:

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

Không có kích hoạt hoặc khóa ngoại được xác định trên bất kỳ bảng nào trong toàn bộ cơ sở dữ liệu.

Bản dựng SQL Server chính xác là:

Microsoft SQL Server 2012 (SP3-CU4) (KB3165264) - 11.0,6540.0 (X64)
23 tháng 6 2016 17:45:11 Bản quyền (c) Microsoft Corporation Enterprise Edition: Cấp phép dựa trên lõi (64-bit) trên Windows NT 6.3 ( Xây dựng 14393 :) (Hypervisor)

Các sự kiện mở rộng khá đơn giản, chỉ cần ghi nhật ký các báo cáo quá trình bị chặn:

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

Cơ sở dữ liệu được định cấu hình trong Đọc cách ly ảnh chụp đã cam kết và mức độ song song tối đa được đặt thành 1. Đây là cấu hình máy chủ:

+------------------------------------+-------+
|                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 |
+------------------------------------+-------+

Tôi đã chạy theo dõi phía máy chủ một lúc và tôi nhận được các nút trống tương tự trong tệp theo dõi khi tôi sử dụng các sự kiện mở rộng.
Báo cáo quy trình bị chặn này đã được ghi lại bằng cách sử dụng dấu vết phía máy chủ trên một máy chủ khác cũng đang chạy Dynamics AX, do đó, nó không dành riêng cho máy chủ hoặc bản dựng này.

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

Có ai có một lời giải thích cho các báo cáo này? Điều gì đang chặn truy vấn?

Có cách nào để tìm hiểu những gì đang xảy ra nếu tôi xem các báo cáo sau khi các khóa đã mất từ ​​lâu?

Một điều có thể hữu ích để thêm là các truy vấn này được chạy qua sp_cursorpreparesp_cursorexecute

Cho đến nay tôi đã không thể tái tạo nó, nó dường như xảy ra ngẫu nhiên nhưng rất thường xuyên.

Nó xảy ra trên một số trường hợp (của các bản dựng khác nhau) và một số bảng / truy vấn, tất cả đều liên quan đến Dynamics AX.

Không có chỉ mục hoặc công việc bảo trì cơ sở dữ liệu khác xảy ra trong nền tại thời điểm đó.

Sử dụng mã được cung cấp trong câu trả lời của srutzky, tôi có thể ghi lại một số ghi nhật ký liên quan đến báo cáo quy trình bị chặn này:

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

Điều này được tìm thấy trong các bảng ghi nhật ký cho cùng một tài nguyên trong khoảng thời gian đó: Gist vì giới hạn ký tự

Điều tra sâu hơn cho thấy rằng ngay trước và sau báo cáo với quy trình chặn trống, tôi có các báo cáo cho cùng một tài nguyên có các nút quy trình chặn:

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

Sử dụng tập lệnh mới được cung cấp bởi srutzky dữ liệu mới đã được thu thập. Nó được đăng trên github vì độ dài bài tối đa.

Vì dữ liệu được đăng ban đầu không có cả id phiên, một số dữ liệu mới đã được đăng lại trên github

Dữ liệu mới bao gồm các kết nối trên github

Câu trả lời:


6

Tôi không thể kiểm tra lý thuyết này vào lúc này, nhưng dựa trên dữ liệu chụp gần đây nhất được đăng lên GitHub , tôi sẽ nói rằng lý do <process>nút đó trống là vì nó yêu cầu một yêu cầu hiện đang chạy (nhiều thuộc tính được tìm thấy trong sys.dm_exec_requestsvà không có sys.dm_exec_sessions) và không có yêu cầu hiện đang chạy, nó không thể báo cáo bất kỳ chi tiết nào, tương tự như cách thực hiện INNER JOINgiữa sys.dm_exec_requestssys.dm_exec_sessionssẽ loại trừ các hàng nơi Phiên hoạt động nhưng không hoạt động do không có yêu cầu hiện tại.

Nhìn vào tập dữ liệu hàng đầu ( monitorLoopcác giá trị: 1748823, 1748824, 1748825 và 1748827) chúng ta có thể thấy như sau:

  • các idcủa blocked-processlà như nhau trong mỗi trường hợp: process2552c1fc28 , và thuộc tính duy nhất mà là khác nhau là waittime(dễ hiểu).
  • các thuộc tính của các blocking-processnút cho thấy sự khác biệt trong cả hai lastbatchstartedlastbatchcompleted
  • các thuộc tính của các blocking-processnút hiển thị các giá trị giống hệt nhau cho spidxactid

Vậy, làm thế nào để sessionID và TransactionID của quá trình chặn có thể giống nhau trên 4 lô truy vấn khác nhau? Dễ dàng, một giao dịch rõ ràng đã được bắt đầu và sau đó các lô này đã được thực hiện. Và bởi vì đây là các lô riêng biệt, nên có thời gian giữa chúng được gửi, tại thời điểm đó không có yêu cầu hiện tại, do đó không có thông tin quy trình nào để hiển thị (nhưng phiên và giao dịch vẫn còn đó).

Để thực hiện nghiên cứu bổ sung về vấn đề này, bạn có thể nắm bắt thông tin hữu ích từ sys.dm_exec_requestssys.dm_tran_locksbằng cách đặt T-SQL sau vào Bước công việc "Tập lệnh SQL giao dịch (T-SQL)", đặt "Cơ sở dữ liệu" thành một bạn đang nghiên cứu (trong trường hợp này là một người có ID là 6) và lên lịch cho công việc này để chạy cứ sau 10 giây. T-SQL bên dưới sẽ tạo hai bảng trong cùng một DB nếu chúng không tồn tại và sau đó sẽ điền vào bảng "Yêu cầu" nếu bất kỳ yêu cầu nào tự chặn hoặc nếu đó là thao tác Xóa hoặc Cập nhật đang bị chặn . Nếu bất kỳ yêu cầu nào được tìm thấy, nó sẽ cố gắng nắm bắt:

  • Thông tin về Phiên và Yêu cầu về quy trình chặn (phần này không cho rằng có Yêu cầu hoạt động, do đó RIGHT JOINít nhất phải có được thông tin Phiên)
  • Thông tin kết nối cho các quá trình chặn và (hy vọng) bị chặn.
  • các khóa hiện tại cho cùng một session_id (hãy nhớ rằng thông tin khóa không được đảm bảo chính xác 100% vì thông tin đó có thể thay đổi theo thời gian giữa hai câu lệnh đang thực thi; tuy nhiên, thông tin đủ thường xuyên đủ để có đáng để nắm bắt). Phần này hiện đang được bình luận.

Công việc SQL-Tác nhân T-SQL Bước:

-- !! 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
                                     );
 */

Tôi nghĩ bạn sẽ có thể tái tạo điều này bằng cách mở một tab truy vấn và thực hiện như sau:

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

Sau đó, mở tab truy vấn thứ hai và thực hiện như sau:

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

PS Chỉ cần nói rõ, điều duy nhất không có ý nghĩa là thông tin về yêu cầu và phiên - dbo.tmpBlockingResearch_Requests- vẫn không bao giờ chứa các hàng cho phiên chặn. Tuy nhiên, tôi biết rằng biến bảng có id phiên chặn trong đó vì nó đã khóa các khóa cho cả hai phiên. Điều này có thể chỉ ra một kịch bản trong đó Giao dịch được phép mở sau khi "kết nối" từ máy khách bị đóng nhưng kết nối vẫn được duy trì do Kết nối nhóm.


@TomV Tôi đã xem xét dữ liệu nghiên cứu mới nhất và có một lý thuyết khá vững chắc. Tôi đã cập nhật câu trả lời của mình cho phù hợp, bao gồm thêm một phần vào các truy vấn nghiên cứu của mình, vì vậy vui lòng thay thế bước công việc SQL bằng các truy vấn mới tại đây (tôi cũng đã nhận xét truy vấn "khóa" vì chúng tôi không thực sự cần dữ liệu đó ngay bây giờ và đó là rất nhiều dữ liệu). Tôi đề nghị cắt / bỏ các bảng nghiên cứu hiện có để bắt đầu lại từ đầu.
Solomon Rutzky

@TomV Ok. Và tôi đã cập nhật truy vấn repro của mình thành CẬP NHẬT thay vì CHỌN để nó có thể đại diện hơn cho tình huống của bạn. Tôi cũng đã thêm một ghi chú ở cuối về các hàng bị thiếu trong bảng yêu cầu. Hy vọng rằng bảng Kết nối mới ít nhất sẽ xác nhận sự tồn tại liên tục của Phiên bản chặn. (PS, tôi bắt đầu làm sạch ý kiến ​​của tôi ở trên).
Solomon Rutzky

Công việc của bạn đang hoạt động. Tôi sẽ cần tìm một chút thời gian để kiểm tra bản repro và phân tích nó vào tuần tới
Tom V - Đội ngũ Monica

Xin chào Solomon. 2 ví dụ mới đã được đăng trên github. Thật không may, tôi không thể kích hoạt quy trình chặn BPR trống bằng cách sử dụng trường hợp repro được cung cấp.
Tom V - Đội Monica

Nhìn rất nhanh vì tôi không có nhiều thời gian. Có vẻ như thông tin Kết nối cho thấy ID phiên chặn vẫn hoạt động nhưng nó không có trong bảng phiên. Tôi có thể kiểm tra điều này sau, nhưng tôi khá chắc chắn rằng chỉ ra kết nối (kết nối vẫn còn) và kết nối được đóng giữa các lệnh nhưng giao dịch vẫn mở rõ ràng (vì giao dịch_id luôn giống như lần trước chúng ta đã thấy). Sẽ xem xét kỹ hơn sau ..
Solomon Rutzky

4

Giao dịch bị chặn có thể xảy ra do leo thang khóa.

Điều này được giải thích trong bài viết Hỗ trợ của Microsoft:

Cách giải quyết các sự cố chặn do sự leo thang khóa trong SQL Server

...
Khóa leo thang không gây ra hầu hết các vấn đề chặn. Để xác định xem việc leo thang khóa có xảy ra vào khoảng thời gian khi bạn gặp sự cố chặn hay không, hãy bắt đầu theo dõi SQL Profiler bao gồm sự kiện Khóa: Nâng mức. Nếu bạn không thấy bất kỳ sự kiện Khóa: Nâng mức nào, việc leo thang khóa sẽ không xảy ra trên máy chủ của bạn và thông tin trong bài viết này không áp dụng cho tình huống của bạn.

Nếu xảy ra tình trạng leo thang khóa, hãy xác minh rằng khóa bảng leo thang đang chặn người dùng khác
...

Kiểm tra các sự kiện mở rộng (tệp vật lý) để biết các sự kiện leo thang khóa xảy ra trước sự kiện quy trình bị chặn .

Giải thích

Có một bài viết Blog của Microsoft đi sâu vào chi tiết:

Khóa và chặn khóa máy chủ SQL

...
Bước 2: Thu thập khóa nâng cấp và các sự kiện báo cáo quá trình bị chặn.

Khóa leo thang và các sự kiện báo cáo quá trình bị chặn không được SQL Server tự động nắm bắt. Để biết liệu những sự kiện này có xảy ra hay không, chúng ta cần nói với SQL Server để ghi lại chúng. Nhóm của chúng tôi sử dụng Công cụ phân tích hiệu suất cho Microsoft Dynamics để thu thập thông tin đó. Kiểm tra bài đăng này của Rod Hansen để biết thêm thông tin về công cụ và cách thu thập chi tiết chặn với nó. Nếu bạn chỉ muốn sử dụng SQL Server Profiler, các sự kiện bạn cần thu thập sẽ được hiển thị bên dưới: ...

Sau khi bạn đã bắt được các lần leo thang khóa và các quy trình bị chặn, bạn phải xác định xem việc leo thang khóa có phải là nguyên nhân gốc của các quy trình bị chặn hay không:

...
Bước 3: Xem lại Dấu vết trong SQL Server Profiler.

Có hai chỉ số chính sẽ cho bạn biết nếu việc chặn có liên quan đến leo thang khóa.

Đầu tiên, bạn thấy một loạt các sự kiện leo thang khóa ngay trước các sự kiện báo cáo quá trình bị chặn. Dưới đây là một ví dụ được lấy từ một dấu vết được tạo bởi Công cụ phân tích hiệu suất cho Microsoft Dynamics. Đây là một điều cần tìm trong dấu vết, nhưng điều này một mình không có nghĩa là leo thang khóa đang gây ra sự ngăn chặn. ...

và xa hơn

Để xác minh rằng việc chặn thực tế có liên quan đến leo thang khóa, bạn cần xem chi tiết báo cáo quy trình bị chặn. Trong phần TextData, hãy tìm Waitresource (xem ảnh chụp màn hình bên dưới). Nếu Waitresource bắt đầu với ĐỐI TƯỢNG, chúng tôi biết rằng câu lệnh bị chặn đang chờ khóa khóa bảng được phát hành trước khi có thể tiến hành. Nếu Waitresource bắt đầu bằng KEY hoặc PAG thay vì ĐỐI TƯỢNG, thì việc leo thang khóa không liên quan đến khối cụ thể đó . Khóa leo thang sẽ luôn tăng phạm vi của khóa lên OJBECT bất kể nó bắt đầu từ đâu

Dung dịch

(chỉ khi các trận đấu được đề cập ở trên)

Giải pháp rõ ràng là bật cờ theo dõi 1224 sẽ tắt leo thang khóa:

Khóa và chặn khóa máy chủ SQL

Nếu bạn thấy hai điều này cùng nhau, một sự đánh cược khá tốt là việc leo thang khóa đang gây ra sự ngăn chặn và bạn có thể sẽ được hưởng lợi từ việc triển khai cờ theo dõi SQL Server 1224.

SQL Trace Flag cho Dynamics AX

Cờ dấu vết 1224 vô hiệu hóa leo thang khóa dựa trên số lượng khóa. Kích hoạt cờ theo dõi này có thể làm giảm khả năng chặn do leo thang khóa - điều mà tôi đã thấy với một số triển khai AX. Kịch bản phổ biến nhất mà vấn đề này trở thành vấn đề là khi có yêu cầu về Kế hoạch tổng thể để chạy trong ngày

Câu trả lời

Cuối cùng, có thể sự leo thang khóa là nguyên nhân gốc rễ của các quá trình bị chặn.


Giải pháp thay thế (nút xử lý trống)

Sau khi điều tra thêm về một số block_ process_Vports, có thể đưa ra lời giải thích thay thế sau đây.

Các sự kiện mở rộng đang nắm bắt được chặn_Quản lý không liên quan đến bất kỳ quy trình nào khác tại thời điểm đó.

Ergo: Họ phải bị chặn vì một lý do khác

Tôi sẽ đề nghị bạn nắm bắt khung thời gian của các loại chờ từ chế độ xem sys.dm_os_wait_stats trên Máy chủ SQL của bạn và tương quan các số với số bị chặn_Quản lý xảy ra trong các phép đo của bạn. Paul Randall có một kịch bản hay: Gửi cho tôi số liệu thống kê chờ đợi của bạn và nhận lời khuyên của tôi và 30 ngày trở lại Pluralsight miễn phí

Các kịch bản ghi lại các bộ đếm hiện tại, đợi trong 23 giờ (có thể được sửa đổi), lấy lại các bộ đếm hiện tại một lần nữa và so sánh chúng để cung cấp cho bạn 95% loại chờ hàng đầu. Bạn có thể dùng thử trong 1 giờ và có sẵn tệp XEL.

Bạn có thể tìm thấy một loại chờ (ví dụ LCK_M_SH, Hoài) đang nói với bạn rằng bộ nhớ của bạn chậm bằng văn bản. Hoặc là bạn có một số chi phí khác (ví dụ: CX_PACKET_WAITS, tầm.). Một cái gì đó đang làm chậm cập nhật của bạn. Sau đó, bạn có thể xem liệu sys.dm_os_wait_stats có liên quan đến các hàm bị chặn_Quản lý với các nút trống không.

Có những trường hợp khi SPID bị chặn đang bị chặn bởi cùng một SPID:

Cột bị chặn trong bảng sys Processes được điền cho chốt chờ sau khi bạn cài đặt SQL Server 2000 SP4

Khi SPID đang chờ chốt trang I / O, bạn có thể nhận thấy rằng cột bị chặn báo cáo ngắn gọn rằng SPID đang tự chặn. Hành vi này là một tác dụng phụ của cách sử dụng chốt cho các hoạt động I / O trên các trang dữ liệu. Khi một luồng phát hành một yêu cầu I / O, SPID đưa ra yêu cầu I / O có được một chốt trên trang. Tất cả các hoạt động I / O của SQL Server 2000 đều không đồng bộ. Do đó, SPID sẽ cố gắng có được một chốt khác trên cùng trang nếu SPID đã đưa ra yêu cầu I / O phải chờ yêu cầu kết thúc. Chốt thứ hai này bị chặn bởi chốt đầu tiên. Do đó, cột bị chặn báo cáo rằng SPID đang tự chặn. Khi yêu cầu I / O kết thúc, chốt đầu tiên được giải phóng. Sau đó, yêu cầu chốt thứ hai được cấp.

Trả lời thay thế

Đây là một dấu hiệu nữa cho thấy bạn có thể gặp vấn đề IO. Những vấn đề này dẫn đến "các quy trình bị chặn" nhưng không có SPID nước ngoài liên quan. Sự kiện mở rộng có thể không báo cáo quá trình / SPID trong một nút riêng.


Tôi có thể đọc sai điều này, nhưng thông tin này không chứng minh rằng vấn đề không phải là khóa leo thang? Một phần được trích dẫn nói "look at the blocked process report details."và XML nhiều nhất trong câu hỏi là báo cáo quy trình bị chặn. Tiếp theo, phần được trích dẫn đó nói "If waitresource starts with KEY or PAG instead of OBJECT, then lock escalation isn’t involved in that specific block.", và các chương trình XML báo cáo quy trình bị chặn waitresource="KEY: 6:72057..... Vì vậy, điều đó có nghĩa là "khóa leo thang không liên quan" ở đây.
Solomon Rutzky

Không, bạn KHÔNG đọc sai điều này. Phần được cung cấp trong câu hỏi là một vấn đề trên máy chủ này. Câu trả lời của tôi là một cách tiếp cận toàn cầu đối với các vấn đề có thể xảy ra do chặn và khóa leo thang. Nếu bạn có thể khắc phục một số vấn đề lớn (bị chặn_Quản lý khóa đối với khóa cấp đối tượng), thì các sự cố nhỏ hơn (bị chặn_Quản lý ở các cấp độ khác) có thể tự giải quyết. Đây là lý do tại sao tôi cũng đã thêm một câu trả lời thay thế thứ hai.
John aka hot2use
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.