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:
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.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.
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%%!
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.
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 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!
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: