Nëse po përdorni raportin mbi bllokimet (blocked process report) ose po grumbulloni grafikat e bllokimeve të ofruara nga SQL Server, herë pas here do të përballeni me gjëra të tilla:
waitresource="PAGE: 6:3:70133"
waitresource="KEY: 6:72057594041991168 (ce52f92a058c)"
Ndoshta, në atë XML gjigand që po shqyrtoni, do të ketë më shumë informacion (grafikat e bllokimeve përmbajnë një listë burimesh, e cila ndihmon në identifikimin e emrave të objektit dhe indeksit), por jo gjithmonë.
Ky tekst do t'ju ndihmojë ta kuptoni.
Të gjitha informacionet që janë këtu janë në internet në vende të ndryshme, ato janë thjesht shumë të shpërndara! Dua t'i grumbulloj të gjitha së bashku - nga DBCC PAGE te hobt_id dhe funksionet e pa dokumentuara %%physloc%% dhe %%lockres%%.
Së pari, le të flasim për pritjet në bllokimet PAGE, dhe pastaj të kalojmë te bllokimet KEY.
1) waitresource="PAGE: 6:3:70133" = Id_Baze_Datoj: Id_Fajli: Numri_i_Faqes
Nëse pyetja juaj pret për një bllokim PAGE, SQL Server do t'ju japë adresën e kësaj faqe.
Duke e ndarë "PAGE: 6:3:70133" ne marrim:
- database_id = 6
- data_file_id = 3
- page_numer = 70133
1.1) Shkruajmë database_id
Gjejmë emrin e bazës së të dhënave duke përdorur pyetjen:
SELECT
name
FROM sys.databases
WHERE database_id=6;
GOKjo është publike në SQL Server-in tim.
1.2) KĂ«rkojmĂ« emrin e fajlit tĂ« tĂ« dhĂ«nave â nĂ«se jeni tĂ« interesuar
Do të përdorim data_file_id në hapin tjetër për të gjetur emrin e tabelës. Mund të kaloni thjesht te hapi tjetër, por nëse jeni të interesuar për emrin e fajlit, mund ta gjeni duke ekzekutuar pyetjen në kontekstin e Baza e të Dhënave të gjetur, duke futur data_file_id në këtë pyetje:
USE WideWorldImporters;
GO
SELECT
name,
physical_name
FROM sys.database_files
WHERE file_id = 3;
GONë Baza e të Dhënave WideWorldImporters, ky është një fajll i quajtur WWI_UserData dhe është rikuperuar te C:MSSQLDATAWideWorldImporters_UserData.ndf. (Ups, më kapët teksa vendosja skedarët në disk me sistemin! Jo! Doli në mënyrë të pazakontë).
1.3) Merrni emrin e objektit nga DBCC PAGE
Tani e dimë se faqja #70133 në fajlin e të dhënave 3 i përket Baza e të Dhënave WideWorldImporters. Mund të shohim përmbajtjen e kësaj faqeje duke përdorur DBCC PAGE të pa dokumentuar dhe trace-flag 3604.
ShĂ«nim: preferoj tĂ« pĂ«rdor DBCC PAGE nĂ« njĂ« kopje tĂ« rikuperuar nga backup nĂ« njĂ« server tjetĂ«r, sepse kjo Ă«shtĂ« njĂ« gjĂ« e pa dokumentuar. NĂ« disa raste, ajo (shĂ«nim i pĂ«rkthyesit â lidhja, fatkeqĂ«sisht, nuk çon asgjĂ«, por gjykoj sipas url se bĂ«het fjalĂ« pĂ«r indekset e filtruar).
/* 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 Duke përpara rezultateve, mund të gjeni object_id dhe index_id.

Gati! Tani mund të gjeni emrat e tabelës dhe indeksit përmes pyetjes:
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;
GODhe tani shohim se pritja për bllokimin ishte në indeksin PK_Sales_OrderLines të tabelës Sales.OrderLines.
Shënim: Në SQL Server 2014 dhe më lart, emri i objektit gjithashtu mund të gjendet përmes DMO të pa dokumentuar sys.dm_db_database_page_allocations. Por do t'ju duhet të kërkoni çdo faqe në DB, që duket jo shumë mirë për bazat e të dhënave të mëdha, kështu që unë përdora DBCC PAGE.
1.4) A mund të shohim të dhënat në atë faqe që ishte e bllokuar?
Po, por⊠a jeni absolutisht të sigurt se ju nevojitet kjo?
Kjo është e ngadalshme edhe për tabela të vogla. Por është ndonjëherë interesante, kështu që, për sa kohë keni arritur në këtë pikë⊠le të flasim për %%physloc%%!
%%physloc%% është një copë magjie e pa dokumentuar që kthen identifikuesin fizik për çdo regjistrim. Ju mund ta përdorni .
Tani, kur e dimë se kemi dashur të bllokojmë faqen në Sales.OrderLines, mund të shohim të gjitha të dhënat në këtë tabelë, të cilat ruhen në skedarin e të dhënave #3 në faqe #70133, përmes kësaj pyetjeje:
Use WideWorldImporters;
GO
SELECT
sys.fn_PhysLocFormatter (%%physloc%%),
*
FROM Sales.OrderLines (NOLOCK)
WHERE sys.fn_PhysLocFormatter (%%physloc%%) like '(3:70133%'
GOSiç thashĂ« â kjo Ă«shtĂ« e ngadalshme edhe pĂ«r tabela tĂ« vogla. Kam shtuar NOLOCK nĂ« pyetje sepse nuk kemi asnjĂ« garanci qĂ« tĂ« dhĂ«nat qĂ« duam tĂ« shohim janĂ« ato tĂ« njĂ«jta qĂ« ishin nĂ« momentin qĂ« u zbulua bllokimi â kĂ«shtu qĂ« mund tĂ« bĂ«jmĂ« lehtĂ«sisht leximet e ndotura.
Por, urra, pyetja më kthen ato 25 rreshta që po luftonim për të marrë

Mjaft me bllokimet PAGE. ĂfarĂ« ndodh nĂ«se jemi duke pritur pĂ«r bllokim KEY?
2) waitresource=âKEY: 6:72057594041991168 (ce52f92a058c)â = Database_Id, HOBT_Id (hash magjik qĂ« mund tĂ« dekodifikohet me %%lockres%%, nĂ«se e dĂ«shironi me tĂ« vĂ«rtetĂ«)
Nëse pyetja juaj përpiqet të bllokojë një regjistrim në indeks dhe përfundon duke u bllokuar vetë, merrni një lloj krejtësisht të ndryshëm të adresës.
Duke ndarĂ« â6:72057594041991168 (ce52f92a058c)â nĂ« pjesĂ«, ne marrim:
- database_id = 6
- hobt_id = 72057594041991168
- hashi magjik = (ce52f92a058c)
2.1) Shkruaj database_id
Kjo funksionon pikërisht si shembulli më sipër! Gjejmë emrin e bazës së të dhënave përmes një kërkese:
SELECT
name
FROM sys.databases
WHERE database_id=6;
GONĂ« rastin tim â Ă«shtĂ« akoma e njĂ«jta .
2.2) Shkruaj hobt_id
NĂ« kontekstin e bazĂ«s sĂ« tĂ« dhĂ«nave tĂ« gjetur, duhet tĂ« kryhet njĂ« kĂ«rkesĂ« ndaj sys.partitions me çift join-esh qĂ« ndihmojnĂ« nĂ« pĂ«rcaktimin e emrave tĂ« tabelĂ«s dhe indeksitâŠ
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;
GOAi më thotë se kërkesa ka pritur për bllokimin e Application.Countries, duke përdorur indeksin PK_Application_Countries.
2.3) Tani pak magji %%lockres%% â nĂ«se dĂ«shironi tĂ« zbuloni se cila regjistrim ishte i bllokuar
Nëse vërtet dua të di se mbi cilin rresht ishte nevoja për bllokim, mund ta zbuloj këtë përmes një kërkese ndaj tabelës së vet. Mund të përdorim funksionin e pa dokumentuar %%lockres%% për të gjetur regjistrimin që përputhet me hash-in magjik.
Kujdes, se kjo kërkesë do të skanojë të gjithë tabelën dhe në tabelat e mëdha kjo mund të mos jetë shumë e këndshme:
SELECT
*
FROM Application.Countries (NOLOCK)
WHERE %%lockres%% = '(ce52f92a058c)';
GO Kam shtuar NOLOCK () sepse bllokimet mund tĂ« bĂ«hen problem. Duam thjesht tĂ« shikojmĂ« se çfarĂ« ka tani, jo se çfarĂ« ka pasur kur filloi transaksioni â nuk mendoj se Ă«shtĂ« e rĂ«ndĂ«sishme qĂ« tĂ« dhĂ«nat tĂ« jenĂ« tĂ« qĂ«ndrueshme.
Voila, regjistrimi për të cilin luftuam!

Faleminderit dhe lexim i mëtejshëm
Nuk e mbaj mend se kush e përshkroi për herë të parë shumë nga këto gjëra, por ja dy postime për gjërat më pak të dokumentuara, që mund t'ju interesojnë:
- Postimi i Paul Randal mbi (si i morëm të dhënat tona në shembullin e parë)
- Pyetje në StackOverflow rreth (si gjetëm të dhënat në shembullin e dytë). Një nga përgjigjet çon në postimin .
Burimi: habr.com
