Decipher Key at Page WaitResource sa mga deadlock at lock

Kung gagamitin mo ang naka-block na ulat ng proseso o kinokolekta ang mga deadlock graph na ibinigay ng SQL Server pana-panahon, makakatagpo ka ng mga bagay na tulad nito:

waitresource="PAGE: 6:3:70133"

waitresource=β€œKEY: 6:72057594041991168 (ce52f92a058c)β€œ

Minsan, magkakaroon ng higit pang impormasyon sa higanteng XML na iyon na iyong pinag-aaralan (ang mga deadlock graph ay naglalaman ng isang listahan ng mga mapagkukunan na makakatulong sa iyong malaman ang mga pangalan ng bagay at index), ngunit hindi palaging.

Tutulungan ka ng tekstong ito na maunawaan ang mga ito.

Ang lahat ng impormasyon na narito ay nasa Internet sa iba't ibang mga lugar, ito ay napaka-ipinamahagi! Gusto kong pagsama-samahin ang lahat, mula sa DBCC PAGE hanggang hobt_id hanggang sa hindi dokumentadong %%physloc%% at %%lockres%% function.

Una, pag-usapan natin ang mga paghihintay sa PAGE lock, at pagkatapos ay lumipat sa KEY lock.

1) waitresource="PAGE: 6:3:70133" = Database_Id: FileId: PageNumber

Kung naghihintay ang iyong kahilingan sa lock ng PAGE, ibibigay sa iyo ng SQL Server ang address ng page na iyon.

Ang paghahati-hati sa "PAHINA: 6:3:70133" ay makukuha natin:

  • database_id = 6
  • data_file_id = 3
  • page_number = 70133

1.1) I-decrypt ang database_id

Hanapin ang pangalan ng database gamit ang query:

SELECT 
    name 
FROM sys.databases 
WHERE database_id=6;
GO

Ito ay pampubliko Mga DB WideWorldImporters sa aking SQL Server.

1.2) Hinahanap ang pangalan ng data file - kung interesado ka

Gagamitin namin ang data_file_id sa susunod na hakbang upang mahanap ang pangalan ng talahanayan. Maaari ka lamang lumaktaw sa susunod na hakbang, ngunit kung interesado ka sa pangalan ng file, mahahanap mo ito sa pamamagitan ng pagpapatakbo ng isang query sa konteksto ng nahanap na database, pagpapalit ng data_file_id sa query na ito:

USE WideWorldImporters;
GO
SELECT 
    name, 
    physical_name
FROM sys.database_files
WHERE file_id = 3;
GO

Sa database ng WideWorldImporters ito ay isang file na tinatawag na WWI_UserData at naibalik ko ito sa C:MSSQLDATAWideWorldImporters_UserData.ndf. (Oops, nahuli mo akong naglalagay ng mga file sa system drive! Hindi! Nakakahiya).

1.3) Kunin ang pangalan ng object mula sa DBCC PAGE

Alam na natin na ang page #70133 sa datafile 3 ay kabilang sa database ng WorldWideImporters. Maaari nating tingnan ang mga nilalaman ng pahinang ito gamit ang hindi dokumentadong DBCC PAGE at trace flag 3604.
Tandaan: Mas gusto kong gumamit ng DBCC PAGE sa isang naibalik na kopya sa isang lugar sa ibang server, dahil ito ay hindi dokumentado. Sa ilang mga kaso, siya maaaring magresulta sa isang tambakan (tinatayang tagasalin - ang link, sa kasamaang-palad, ay hindi humahantong saanman, ngunit sa paghusga sa pamamagitan ng url, pinag-uusapan natin ang tungkol sa mga na-filter na index).

/* This trace flag makes DBCC PAGE output go to our Messages tab
instead of the SQL Server Error Log file */
DBCC TRACEON (3604);
GO
/* DBCC PAGE (DatabaseName, FileNumber, PageNumber, DumpStyle)*/
DBCC PAGE ('WideWorldImporters',3,70133,2);
GO

Sa pamamagitan ng pag-scroll sa mga resulta, mahahanap mo ang object_id at index_id.
Decipher Key at Page WaitResource sa mga deadlock at lock
Halos tapos na! Ngayon ay mahahanap mo na ang mga pangalan ng talahanayan at index na may query:

USE WideWorldImporters;
GO
SELECT 
    sc.name as schema_name, 
    so.name as object_name, 
    si.name as index_name
FROM sys.objects as so 
JOIN sys.indexes as si on 
    so.object_id=si.object_id
JOIN sys.schemas AS sc on 
    so.schema_id=sc.schema_id
WHERE 
    so.object_id = 94623380
    and si.index_id = 1;
GO

At dito makikita natin na ang paghihintay sa lock ay nasa PK_Sales_OrderLines index ng Sales.OrderLines table.

Tandaan: Sa SQL Server 2014 at mas bago, ang pangalan ng object ay makikita din gamit ang undocumented DMO sys.dm_db_database_page_allocations. Ngunit kailangan mong i-query ang bawat pahina sa database, na mukhang hindi masyadong cool para sa malalaking database, kaya ginamit ko ang DBCC PAGE.

1.4) Posible bang makita ang data sa pahinang na-block?

Nuuu, oo. Ngunit... sigurado ka bang kailangan mo ito?
Mabagal kahit sa maliliit na mesa. Ngunit ito ay medyo cool, kaya dahil nabasa mo na ito hanggang ngayon...pag-usapan natin ang tungkol sa %%physloc%%!

Ang %%physloc%% ay isang undocumented na piraso ng magic na nagbabalik ng pisikal na ID para sa bawat entry. pwede mong gamitin %%physloc%% kasama ang sys.fn_PhysLocFormatter sa SQL Server 2008 at mas mataas.

Ngayong alam na namin na gusto naming i-block ang pahina sa Sales.OrderLines, maaari naming tingnan ang lahat ng data sa talahanayang ito, na nakaimbak sa data file #3 sa pahina #70133, na may sumusunod na query:

Use WideWorldImporters;
GO
SELECT 
    sys.fn_PhysLocFormatter (%%physloc%%),
    *
FROM Sales.OrderLines (NOLOCK)
WHERE sys.fn_PhysLocFormatter (%%physloc%%) like '(3:70133%'
GO

Gaya nga ng sabi ko, mabagal kahit sa maliliit na mesa. Idinagdag ko ang NOLOCK sa kahilingan dahil wala pa rin kaming garantiya na ang data na gusto naming tingnan ay eksaktong kapareho ng noong panahong natuklasan ang lock - upang ligtas kaming makagawa ng maruruming pagbabasa.
Ngunit, hooray, ibinabalik sa akin ng query ang mismong 25 row na pinaglabanan ng aming query.
Decipher Key at Page WaitResource sa mga deadlock at lock
Sapat na tungkol sa PAGE lock. Paano kung naghihintay tayo ng KEY lock?

2) waitresource="KEY: 6:72057594041991168 (ce52f92a058c)" = Database_Id, HOBT_Id (magic hash na maaaring i-decrypt gamit ang %%lockres%% kung gusto mo talaga)

Kung ang iyong query ay sumusubok na i-lock ang isang index entry at ma-lock sa sarili nitong, makakakuha ka ng isang ganap na naiibang uri ng address.
Hinahati-hati ang β€œ6:72057594041991168 (ce52f92a058c)” sa mga bahagi, makukuha natin ang:

  • database_id = 6
  • hobt_id = 72057594041991168
  • magic hash = (ce52f92a058c)

2.1) I-decrypt ang database_id

Gumagana ito nang eksakto katulad ng sa halimbawa sa itaas! Nahanap namin ang pangalan ng database gamit ang query:

SELECT 
    name 
FROM sys.databases 
WHERE database_id=6;
GO

Sa aking kaso, ito ay pareho Mga DB WideWorldImporters.

2.2) I-decrypt ang hobt_id

Sa konteksto ng nahanap na database, kailangan mong i-query ang sys.partitions na may ilang mga pagsali na makakatulong na matukoy ang mga pangalan ng talahanayan at index ...

USE WideWorldImporters;
GO
SELECT 
    sc.name as schema_name, 
    so.name as object_name, 
    si.name as index_name
FROM sys.partitions AS p
JOIN sys.objects as so on 
    p.object_id=so.object_id
JOIN sys.indexes as si on 
    p.index_id=si.index_id and 
    p.object_id=si.object_id
JOIN sys.schemas AS sc on 
    so.schema_id=sc.schema_id
WHERE hobt_id = 72057594041991168;
GO

Sinasabi nito sa akin na ang kahilingan ay naghihintay sa Application.Countries lock gamit ang PK_Application_Countries index.

2.3) Ngayon para sa ilang %%lockres%% magic - kung gusto mong malaman kung aling entry ang naka-lock

Kung talagang gusto kong malaman kung saang row ang lock ay kailangan, maaari kong malaman sa pamamagitan ng pagtatanong sa talahanayan mismo. Magagamit namin ang undocumented %%lockres%% function para maghanap ng entry na tumutugma sa magic hash.
Tandaan na ang query na ito ay i-scan ang buong talahanayan, at sa malalaking talahanayan ay maaaring hindi ito maging masaya:

SELECT
    *
FROM Application.Countries (NOLOCK)
WHERE %%lockres%% = '(ce52f92a058c)';
GO

Nagdagdag ako ng NOLOCK (sa payo ni Klaus Aschenbrenner sa twitter) dahil maaaring maging problema ang mga lock. Gusto lang naming tingnan kung ano ang mayroon ngayon, at hindi kung ano ang nandoon noong nagsimula ang transaksyon - Sa palagay ko ay hindi mahalaga sa amin ang pagkakapare-pareho ng data.
Voila, ang record na pinaglaban natin!
Decipher Key at Page WaitResource sa mga deadlock at lock

Pasasalamat at karagdagang pagbabasa

Hindi ko matandaan kung sino ang unang naglarawan sa marami sa mga bagay na ito, ngunit narito ang dalawang post tungkol sa hindi gaanong dokumentado na mga bagay na maaaring gusto mo:

Pinagmulan: www.habr.com

Magdagdag ng komento