กระบวนการบล็อกว่างเปล่าในรายงานกระบวนการที่ถูกบล็อก


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)
23 มิถุนายน 2559 17:45:11 ลิขสิทธิ์ (c) Microsoft Corporation รุ่นองค์กรองค์กร: สิทธิ์การใช้งานแบบคอร์ (64 บิต) บน Windows NT 6.3 ( สร้าง 14393:) (Hypervisor)

เหตุการณ์เพิ่มเติมนั้นค่อนข้างง่ายเพียงบันทึกรายงานกระบวนการที่ถูกบล็อก:

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_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เพราะความยาวโพสต์สูงสุด

เนื่องจากข้อมูลที่โพสต์แรกเริ่มไม่มีทั้งรหัสเซสชันข้อมูลใหม่บางอย่างจึงถูกโพสต์บน Github อีกครั้ง

ข้อมูลใหม่รวมถึงการเชื่อมต่อบน GitHub

คำตอบ:


6

ฉันไม่สามารถทดสอบทฤษฎีนี้ในขณะนี้ แต่จากข้อมูลการดักจับล่าสุดที่โพสต์ไปที่ GitHubฉันจะบอกว่าสาเหตุที่<process>โหนดเจ้าว่างเปล่าก็คือมันต้องการคำขอที่กำลังทำงานอยู่ในขณะนี้sys.dm_exec_requestsและไม่ได้อยู่ในsys.dm_exec_sessions) และหากไม่มีคำขอที่กำลังทำงานอยู่จะไม่สามารถรายงานรายละเอียดใด ๆ ได้เช่นเดียวกับวิธีดำเนินการINNER JOINระหว่าง sys.dm_exec_requestsและsys.dm_exec_sessionsจะไม่รวมแถวที่เซสชันใช้งานอยู่ แต่ไม่มีการใช้งานเนื่องจากไม่มีคำขอปัจจุบัน

ดูชุดข้อมูลด้านบน ( monitorLoopค่า: 1748823, 1748824, 1748825 และ 1748827) เราสามารถดูสิ่งต่อไปนี้:

  • idของblocked-processจะเหมือนกันในแต่ละกรณี: process2552c1fc28และคุณลักษณะเฉพาะที่แตกต่างคือwaittime(เข้าใจ)
  • คุณลักษณะของblocking-processโหนดแสดงความแตกต่างในทั้งสองlastbatchstartedและlastbatchcompleted
  • คุณลักษณะของblocking-processโหนดแสดงค่าที่เหมือนกันสำหรับspidและxactid

ดังนั้น SessionID และ TransactionID ของกระบวนการบล็อกจะเหมือนกันใน 4 ชุดการสืบค้นที่แตกต่างกันได้อย่างไร ง่ายธุรกรรมที่ชัดเจนเริ่มต้นแล้วดำเนินการแบทช์เหล่านี้ และเนื่องจากสิ่งเหล่านี้เป็นแบตช์แยกต่างหากจึงมีเวลาระหว่างการส่งซึ่ง ณ จุดนั้นไม่มีการร้องขอปัจจุบันดังนั้นจึงไม่มีข้อมูลกระบวนการที่จะแสดง (แต่เซสชันและธุรกรรมยังคงอยู่ที่นั่น)

ในการทำวิจัยเพิ่มเติมเกี่ยวกับเรื่องนี้คุณสามารถจับข้อมูลที่เป็นประโยชน์จากsys.dm_exec_requestsและsys.dm_tran_locksโดยการวาง T-SQL ต่อไปนี้ในขั้นตอนการทำงาน "ตัวแทน SQL สคริปต์ (T-SQL)" SQL ธุรกรรมตัวแทน (T-SQL) การตั้งค่า "ฐานข้อมูล" เป็น อันที่คุณกำลังทำการวิจัย (ในกรณีนี้มันคืออันที่มี ID เป็น 6) และกำหนดเวลาให้งานนี้รันทุก ๆ 10 วินาที T-SQL ด้านล่างจะสร้างตารางสองตารางในฐานข้อมูลเดียวกันหากไม่มีอยู่และจะเติมตาราง "คำขอ" หากคำขอใด ๆ กำลังบล็อกตัวเองหรือหากเป็นการลบหรืออัปเดตการดำเนินการที่ถูกบล็อก . หากพบคำขอใด ๆ ก็จะพยายามจับภาพ:

  • ข้อมูลเซสชันและคำขอเกี่ยวกับกระบวนการบล็อก (ส่วนนี้ไม่คิดว่ามีคำขอที่ใช้งานอยู่ดังนั้น RIGHT JOINอย่างน้อยที่สุดจะได้รับข้อมูลเซสชัน)
  • ข้อมูลการเชื่อมต่อสำหรับกระบวนการบล็อกและ (หวังว่า)
  • การล็อกปัจจุบันสำหรับ session_id เดียวกันนั้น (โปรดจำไว้ว่าข้อมูลการล็อคไม่รับประกันความถูกต้อง 100% เนื่องจากข้อมูลนั้นสามารถเปลี่ยนแปลงได้ในช่วงเวลาระหว่างคำสั่งสองคำสั่งที่ดำเนินการอยู่ แต่ถึงกระนั้นข้อมูลก็ดีพอที่จะเพียงพอ มูลค่าการจับภาพ) ส่วนนี้มีการแสดงความคิดเห็น

ขั้นตอนงาน T-SQL Agent Agent ของ SQL Server:

-- !! 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 ทั้งสอง สิ่งนี้อาจชี้ให้เห็นถึงสถานการณ์ที่ธุรกรรมได้รับอนุญาตให้เปิดค้างอยู่หลังจาก "การเชื่อมต่อ" จากไคลเอนต์ถูกปิด แต่การเชื่อมต่อยังคงอยู่เนื่องจากการเชื่อมต่อรวม


@TomV ฉันได้ตรวจสอบข้อมูลการวิจัยล่าสุดและมีทฤษฎีที่มั่นคง ฉันได้อัปเดตคำตอบของฉันแล้วรวมถึงการเพิ่มหัวข้อลงในคิวรีการวิจัยของฉันดังนั้นโปรดแทนที่ SQL ขั้นตอนงานด้วยคำสั่งใหม่ที่นี่ (ฉันใส่เครื่องหมายคำถาม "ล็อค" เนื่องจากเราไม่ต้องการข้อมูลในตอนนี้และ มันเป็นข้อมูลจำนวนมาก) ฉันแนะนำให้ตัดทอน / ดร็อปตารางการวิจัยที่มีอยู่เพื่อเริ่มต้นใหม่ตั้งแต่ต้น
โซโลมอน Rutzky

@TomV ตกลง และฉันได้อัปเดตข้อความค้นหาซ้ำเป็น UPDATE แทนที่จะเป็น SELECT ดังนั้นจึงควรเป็นตัวแทนของสถานการณ์ของคุณต่อไป ฉันยังเพิ่มบันทึกย่อในตอนท้ายเกี่ยวกับแถวที่หายไปในตารางคำขอ หวังว่าตารางการเชื่อมต่อใหม่อย่างน้อยจะยืนยันการมีอยู่อย่างต่อเนื่องของการบล็อก SessionID (PS ฉันเริ่มล้างความคิดเห็นของฉันด้านบน)
โซโลมอน Rutzky

งานของคุณทำงานอยู่ ฉันจะต้องหาเวลาเพื่อทดสอบความซ้ำซ้อนและวิเคราะห์ในสัปดาห์หน้า
ทอมวี - ทีมโมนิก้า

สวัสดีโซโลมอน มีการโพสต์ตัวอย่างใหม่ 2 รายการบน github น่าเสียดายที่ฉันไม่สามารถเรียกใช้กระบวนการบล็อก BPR ที่ว่างเปล่าโดยใช้กรณีตัวพิมพ์ที่ให้มา
Tom V - Team Monica

ใช้เวลาดูอย่างรวดเร็วมากเพราะฉันไม่มีเวลามาก ดูเหมือนว่าข้อมูลการเชื่อมต่อจะแสดง ID การปิดกั้นเซสชันที่ยังใช้งานอยู่ แต่ไม่ได้อยู่ในตารางเซสชัน ฉันสามารถทดสอบได้ในภายหลัง แต่ฉันค่อนข้างแน่ใจว่าบ่งชี้ถึงการรวมการเชื่อมต่อ (การเชื่อมต่อยังคงอยู่ที่นั่น) และการเชื่อมต่อถูกปิดระหว่างคำสั่ง แต่การทำธุรกรรมนั้นเปิดอย่างชัดเจน (เนื่องจาก transaction_id เหมือนเดิมทุกครั้งที่เห็น) จะตรวจสอบอีกครั้งในภายหลัง ..
โซโลมอน Rutzky

4

ธุรกรรมที่ถูกบล็อคสามารถเกิดขึ้นได้เนื่องจากการเพิ่มการล็อค

นี่คือคำอธิบายในบทความ Microsoft Support:

วิธีการแก้ไขปัญหาการบล็อกที่เกิดจากการเลื่อนระดับการล็อกใน SQL Server

...
เลื่อนระดับการล็อคไม่ทำให้เกิดปัญหาการบล็อกมากที่สุด เมื่อต้องการตรวจสอบว่าการเพิ่มระดับการล็อกเกิดขึ้นในช่วงเวลาที่คุณประสบปัญหาการบล็อกหรือไม่ให้เริ่มการสืบค้นกลับของ SQL Profiler ที่มีเหตุการณ์ Lock: การเลื่อนระดับ หากคุณไม่เห็นเหตุการณ์การล็อค: การเลื่อนลำดับใด ๆ การเลื่อนระดับการล็อกจะไม่เกิดขึ้นบนเซิร์ฟเวอร์ของคุณและข้อมูลในบทความนี้จะไม่นำไปใช้กับสถานการณ์ของคุณ

หากการเลื่อนระดับการล็อคเกิดขึ้นตรวจสอบว่าการล็อคตารางที่เลื่อนระดับกำลังบล็อกผู้ใช้รายอื่น
...

ตรวจสอบ Extended Events (ฟิสิคัลไฟล์) สำหรับเหตุการณ์การเลื่อนระดับการล็อกที่เกิดขึ้นก่อนกระบวนการที่ถูกบล็อกเหตุการณ์

อธิบาย

มีบทความในบล็อกของ Microsoft ที่ให้รายละเอียดเพิ่มเติม:

การเลื่อนระดับและการบล็อก SQL Server Lock

...
ขั้นตอนที่ 2: รวบรวมการเพิ่มการล็อคและเหตุการณ์รายงานกระบวนการที่ถูกบล็อก

การเลื่อนระดับการล็อคและเหตุการณ์รายงานกระบวนการที่ถูกบล็อกจะไม่ถูกบันทึกโดยอัตโนมัติโดย SQL Server เพื่อที่จะทราบว่าเหตุการณ์เหล่านี้เกิดขึ้นหรือไม่เราจำเป็นต้องแจ้งให้ SQL Server บันทึกเหตุการณ์เหล่านั้น ทีมของเราใช้เครื่องมือวิเคราะห์ประสิทธิภาพสำหรับ Microsoft Dynamics เพื่อรวบรวมข้อมูล ลองอ่านโพสต์นี้โดย Rod Hansen สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเครื่องมือและวิธีการรวบรวมรายละเอียดการบล็อกด้วย หากคุณต้องการใช้ SQL Server Profiler เหตุการณ์ที่คุณต้องรวบรวมมีดังนี้: ...

หลังจากคุณได้บันทึกการเลื่อนระดับการล็อคและกระบวนการที่ถูกบล็อกคุณต้องพิจารณาว่าการเลื่อนระดับการล็อคเป็นสาเหตุหลักของกระบวนการที่ถูกบล็อกหรือไม่:

...
ขั้นตอนที่ 3: ตรวจสอบการสืบค้นกลับใน SQL Server Profiler

มีตัวบ่งชี้หลักสองตัวที่จะบอกคุณว่าการบล็อกเกี่ยวข้องกับการเลื่อนระดับการล็อกหรือไม่

ก่อนอื่นคุณจะเห็นชุดของเหตุการณ์การเลื่อนระดับการล็อกก่อนหน้าเหตุการณ์รายงานกระบวนการที่ถูกบล็อกทันที ด้านล่างนี้เป็นตัวอย่างที่นำมาจากการติดตามที่สร้างขึ้นโดยเครื่องมือวิเคราะห์ประสิทธิภาพสำหรับ Microsoft Dynamics นี่เป็นสิ่งหนึ่งที่ต้องมองหาในการสืบค้นกลับ แต่สิ่งนี้ไม่ได้หมายความว่าการเพิ่มระดับการล็อคทำให้เกิดการบล็อก ...

และต่อไป

ในการตรวจสอบว่าการบล็อกนั้นเกี่ยวข้องกับการเพิ่มระดับการล็อกคุณต้องดูรายละเอียดรายงานกระบวนการที่ถูกบล็อก ในส่วน TextData ให้ค้นหา waitresource (ดูภาพหน้าจอด้านล่าง) หาก waitresource เริ่มต้นด้วย OBJECT เรารู้ว่าคำสั่งที่ถูกบล็อกกำลังรอการล็อกระดับตารางที่จะนำออกใช้ก่อนที่จะสามารถดำเนินการต่อได้ หาก waitresource เริ่มต้นด้วยKEYหรือPAGแทนที่จะเป็น OBJECT การเพิ่มการล็อคจะไม่เกี่ยวข้องกับบล็อกนั้น การเพิ่มล็อคจะเพิ่มขอบเขตของการล็อกเป็น OJBECT เสมอไม่ว่าจะเริ่มต้นที่ใด

วิธีการแก้

(เฉพาะในกรณีที่การแข่งขันดังกล่าวข้างต้น)

เห็นได้ชัดว่าวิธีแก้ปัญหาคือการเปิดการตั้งค่าสถานะการสืบค้นกลับ 1224 ซึ่งจะปิดการเพิ่มการล็อค:

การเลื่อนระดับและการบล็อก SQL Server Lock

หากคุณเห็นสองสิ่งนี้เข้าด้วยกันมันเป็นสิ่งที่ดีที่การเพิ่มระดับการล็อกทำให้เกิดการบล็อกและคุณอาจได้รับประโยชน์จากการติดตั้งสถานะการสืบค้นกลับของ SQL Server 1224

การติดตามสถานะของเซิร์ฟเวอร์ SQL สำหรับ Dynamics AX

ค่าสถานะการสืบค้นกลับ 1224 ปิดใช้งานการเลื่อนระดับการล็อกตามจำนวนการล็อก การเปิดใช้งานการตั้งค่าสถานะการสืบค้นกลับนี้สามารถลดโอกาสในการบล็อกเนื่องจากการล็อกการเลื่อนระดับ - สิ่งที่ฉันเห็นด้วยการใช้งาน AX จำนวนมาก สถานการณ์ที่พบบ่อยที่สุดซึ่งเป็นปัญหาคือเมื่อมีความต้องการให้การวางแผนหลักทำงานในระหว่างวัน

ตอบ

ในที่สุดอาจเป็นได้ว่าการเพิ่มล็อคเป็นสาเหตุของกระบวนการที่ถูกบล็อก


โซลูชันสำรอง (กระบวนการโหนดว่างเปล่า)

หลังจากการตรวจสอบเพิ่มเติมบางส่วนที่ถูกบล็อก _process_reports คำอธิบายทางเลือกต่อไปนี้สามารถทำได้

เหตุการณ์ขยายกำลังจับภาพ block_process_reports ซึ่งไม่เกี่ยวข้องกับกระบวนการอื่น ๆ ในเวลานั้น

Ergo: พวกเขาจะต้องถูกบล็อกด้วยเหตุผลอื่น

ฉันขอแนะนำให้คุณจับกรอบเวลาของประเภทการรอจากมุมมอง sys.dm_os_wait_stats บน SQL Server ของคุณและเชื่อมโยงตัวเลขกับการบล็อคที่ถูกบล็อกในกระบวนการของคุณ Paul Randall มีสคริปต์ที่ดี: ส่งสถิติการรอคอยของคุณมาให้ฉันและรับคำแนะนำของฉันและรับคืน Pluralsight ฟรี 30 วัน

สคริปต์จับตัวนับปัจจุบันรอ 23 ชั่วโมง (สามารถแก้ไขได้) ปรับขนาดตัวนับปัจจุบันอีกครั้งและเปรียบเทียบเพื่อให้ 95% สูงสุดของประเภทการรอ คุณสามารถลองใช้งานเป็นเวลา 1 ชั่วโมงและใช้ไฟล์ XEL ได้

คุณอาจพบประเภทการรอ (เช่น LCK_M_SH, ... ) ที่บอกคุณว่าที่เก็บข้อมูลของคุณช้าในการเขียน หรือว่าคุณมีค่าใช้จ่ายอื่น ๆ (เช่น CX_PACKET_WAITS, ….) มีบางอย่างกำลังทำให้การอัปเดตของคุณช้าลง จากนั้นคุณสามารถดูว่า sys.dm_os_wait_stats เกี่ยวข้องกับบล๊อคที่ถูกบล็อคด้วยกระบวนการที่ว่างเปล่าหรือไม่

มีหลายกรณีที่ SPID ที่ถูกบล็อคจะถูกบล็อคโดย SPID เดียวกัน:

คอลัมน์ที่ถูกบล็อกในตาราง sysprocesses จะถูกเติมเพื่อรอการรอหลังจากคุณติดตั้ง SQL Server 2000 SP4

เมื่อ SPID กำลังรอ latch หน้า I / O คุณอาจสังเกตเห็นว่าคอลัมน์ที่ถูกบล็อกรายงานโดยย่อว่า SPID กำลังบล็อกตัวเอง พฤติกรรมนี้เป็นผลข้างเคียงของวิธีการใช้แลตช์สำหรับการดำเนินการ I / O บนหน้าข้อมูล เมื่อเธรดออกคำขอ I / O SPID ที่ออกคำขอ I / O จะได้รับ latch บนหน้า การดำเนินงาน SQL Server 2000 I / O ทั้งหมดเป็นแบบอะซิงโครนัส ดังนั้น SPID จะพยายามรับ latch อื่นในหน้าเดียวกันหาก SPID ที่ออกคำขอ I / O ต้องรอให้คำขอเสร็จสิ้น กลอนที่สองนี้ถูกบล็อคโดยสลักแรก ดังนั้นคอลัมน์ที่ถูกบล็อกรายงานว่า 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." XML waitresource="KEY: 6:72057....นั่นหมายความว่า "การเพิ่มล็อคไม่เกี่ยวข้อง" ที่นี่
โซโลมอน Rutzky

ไม่คุณไม่ได้อ่านผิด ส่วนที่ให้ไว้ในคำถามคือปัญหาหนึ่งในเซิร์ฟเวอร์นี้ คำตอบของฉันคือวิธีการระดับโลกในการแก้ไขปัญหาที่อาจเกิดขึ้นเนื่องจากการบล็อกและการเพิ่มการล็อค หากคุณสามารถแก้ไขปัญหาที่สำคัญบางอย่าง (บล็อก _process_reports สำหรับการล็อกระดับ OBJECT) ปัญหาที่มีขนาดเล็กกว่า (บล็อก _process_reports ในระดับอื่น ๆ ) อาจแก้ไขได้ นี่คือเหตุผลที่ฉันได้เพิ่มคำตอบทางเลือกที่สอง
John aka hot2use
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.