Deơifreerime Key ja Page WaitResource deadlock’id ja lukustused

Kui kasutate blokeeritud protsesside aruannet (blocked process report) vĂ”i kogute SQL Serveri poolt pakutavaid deadlock graafe perioodiliselt, siis vĂ”ite aeg-ajalt kokku puutuda jĂ€rgmist tĂŒĂŒpi asjadega:

waitresource="PAGE: 6:3:70133"

waitresource="KEY: 6:72057594041991168 (ce52f92a058c)"

MÔnikord on selles hiiglaslikus XML-is, mida te uurite, rohkem teavet (deadlock graafid sisaldavad ressursside loetelu, mis aitab tuvastada objekti ja indeksi nimed), aga see ei ole alati nii.

See tekst aitab teil neid deĆĄifreerida.

Kogu teave, mis siin on, on internetis eri kohtades, lihtsalt vĂ€ga hajutatuna! Ma tahan kĂ”ik kokku koguda – alates DBCC PAGE'ist kuni hobt_id ja dokumenteerimata %%physloc%% ja %%lockres%% funktsioonideni.

Esmalt rÀÀgime PAGE-blokeeringute ootamisest, seejÀrel liigume KEY-blokeeringute juurde.

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

Kui teie pÀring ootab PAGE-blokeeringule, annab SQL Server teile selle lehe aadressi.

LÀbi «PAGE: 6:3:70133» saame:

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

1.1) DeĆĄifreerime database_id

Otsime andmebaasi nime pÀringu abil:

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

See on avalik andmebaas WideWorldImporters minu SQL Serveris.

1.2) Otsime andmefaili nime – kui teid huvitab

Kavandame kasutada data_file_id jÀrgmisel sammul, et leida tabeli nimi. Te vÔite lihtsalt minna jÀrgmisele sammale, aga kui teid huvitab faili nimi, vÔite selle leida, tehes pÀringu leitud andmebaasi kontekstis, asendades data_file_id selles pÀringus:

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

Andmebaasis WideWorldImporters on see fail nimega WWI_UserData ja see on taastatud minu C:MSSQLDATAWideWorldImporters_UserData.ndf. (Ups, tabasite mind failide ketasĂŒsteemi panemise pealt! Ei! NĂŒĂŒd on kohatu!).

1.3) Saame objekti nime DBCC PAGE'ist

NĂŒĂŒd teame, et leht #70133 andmefailis 3 kuulub andmebaasile WorldWideImporters. Saame vaadata selle lehe sisu dokumendivĂ€lise DBCC PAGE'i ja jĂ€lgimislipu 3604 abil.
MĂ€rkus: ma eelistan kasutada DBCC PAGE'i taastatud varukoopia koopia peal kuskil teisel serveril, sest see on dokumendivĂ€line asi. MĂ”nes olukorras vĂ”ib see viia dumpi loomise (tĂ”lki mĂ€rkus – link viib kahjuks tĂŒhjast kohta, aga URL-i pĂ”hjal tĂ”enĂ€oliselt rÀÀgime filtreeritud indeksitest).

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

Tulemusi sirvides vÔib leida object_id ja index_id.
Deơifreerime Key ja Page WaitResource deadlock’id ja lukustused
Peaaegu valmis! NĂŒĂŒd saab tabeli ja indeksi nimed leida pĂ€ringu abil:

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

Ja nĂŒĂŒd nĂ€eme, et ooteaeg lukustamisel oli indeksi PK_Sales_OrderLines tabelis Sales.OrderLines.

MĂ€rkus: SQL Server 2014 ja uuemates saab objekti nime leida ka dokumenteerimata DMO sys.dm_db_database_page_allocations abil. Kuid peate kĂŒsima iga lehe kohta andmebaasis, mis ei tundu vĂ€ga hea suurte andmebaaside puhul, seega kasutasin DBCC PAGE'i.

1.4) Kas on vÔimalik nÀha andmeid lukustatud lehel?

Hmm, jah. Aga... kas olete kindel, et see on teile tÔesti vajalik?
See on aeglane isegi vÀikestes tabelites. Kuid see on kuidagi lahe, seega, kuna olete siiani lugenud... rÀÀgime %%physloc%%-ist!

%%physloc%% on dokumenteerimata tĂŒkk maagia, mis tagastab fĂŒĂŒsilise identifikaatori iga kirje jaoks. Saate kasutada %%physloc%% koos sys.fn_PhysLocFormatter'iga SQL Server 2008 ja uuemates.

NĂŒĂŒd, kui me teame, et tahtsime lukustada lehte tabelis Sales.OrderLines, saame vaadata kĂ”iki selle tabeli andmeid, mis on salvestatud andmefailis #3 lehel #70133, kasutades sellist pĂ€ringut:

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

Nagu ma ĂŒtlesin — see on aeglane isegi tillukestes tabelites. Lisasin pĂ€ringule NOLOCK, kuna meil pole ikkagi mingeid garantiisid, et andmed, mida soovime vaadata, on tĂ€pselt need, mis olid lukustamise avastamise hetkel — nii et saame rahulikult teha musti lugemisi.
Aga, jee, pÀring tagastab mulle need 25 rida, mille nimel meie pÀring vÔitles
Deơifreerime Key ja Page WaitResource deadlock’id ja lukustused
JÀta PAGE-lukustused kÔrvale. Mis siis, kui ootame KEY-lukustust?

2) waitresource=“KEY: 6:72057594041991168 (ce52f92a058c)” = Database_Id, HOBT_Id (maagiline hash, mille saab dekrĂŒpteerida %%lockres%%-iga, kui soovite seda tĂ”esti teha)

Kui teie pĂ€ring ĂŒritab lukustada kirjet indeksis ja jÀÀb ise lukku, saad accessun teistsuguse aadressi tĂŒĂŒbi.
TĂŒkeldades “6:72057594041991168 (ce52f92a058c)” saame:

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

2.1) DekrĂŒpteerime database_id

See töötab tÀpselt samamoodi nagu eespool toodud nÀites! Leiame andmebaasi nime pÀringu abil:

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

Minu puhul on see ikka sama andmebaas WideWorldImporters.

2.2) Dekodeerime hobt_id

Kontekstis leitud andmebaasis tuleb teha pÀring sys.partitions tabelisse, koos paari join'iga, mis aitavad tuvastada tabeli ja indeksi nimed...

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

See ĂŒtleb mulle, et pĂ€ring ootas blokkeeringut Application.Countries, kasutades indeksi PK_Application_Countries.

2.3) NĂŒĂŒd vĂ€ike maagia %%lockres%% — kui soovite teada, milline rekord oli blokeeritud

Kui ma tÔesti tahan teada, millisel real blokkeerimine toimus, vÔin seda vÀlja selgitada pÀringuga iseenda tabeli vastu. Saame kasutada dokumenteerimata funktsiooni %%lockres%%, et leida rekord, mis vastab maagilisele hash'ile.
Pidage meeles, et see pÀring skaneerib kogu tabelit, ja suurte tabelite puhul ei pruugi see olla just kÔige toredam:

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

Lisasin NOLOCK (Klaus Aschenbrenneri soovitusel Twitteris) kuna lukud vĂ”ivad probleemiks osutuda. Soovime lihtsalt vaadata, mis seal hetkel on, mitte mis seal oli, kui tehing algas — ei arva, et andmete jĂ€rjepidevus on meile oluline.
Voilà, rekord, mille nimel me vÔitlesime!
Deơifreerime Key ja Page WaitResource deadlock’id ja lukustused

TĂ€nud ja edasi lugemine

Ei mÀleta, kes esimesena paljusid neist asjadest kirjeldas, aga siin on kaks postitust kÔige vÀhem dokumenteeritud asjadest, mis vÔivad teile meeldida:

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster