W trakcie analizowania blokowań w SQL Server można często spotkać się z wpisami w XML:

waitresource=“PAGE: 7:4:50256 "

lub

waitresource=“KEY: 8:72046656561991169 (cd54f92b253d)”

Co to oznacza ? Jak to przetłumaczyć ?

Pokrótce blokada PAGE występuje na poziomie strony, a KEY na poziomie Klucza no ale po kolei.

Page lock waits

Jeśli mamy wpis

waitresource=“ PAGE: 7:4:50256"

oznacza to, że zapytanie czekało na blokadę na poziomie strony. Silnik podaje nam po kolei

PAGE: 7:4:50256

  • PAGE – blokada na poziomie strony
  • 7 – jest to database_id czyli identyfikator bazy danych
  • 4 – data_file_id – identyfikator pliku bazy danych
  • 50256 – numer strony danych

W celu sprawdzenia jaka to baza o identyfikatorze 7 musimy użyć skryptu:

SELECT name 
FROM sys.databases 
WHERE database_id=7

gdzie uzyskamy nazwę bazy: DBA.

Teraz można znając już nazwę bazy można uzyskać nazwę pliku bazy danych.

USE DBA
SELECT name, physical_name
FROM sys.database_files
WHERE file_id = 4

W odpowiedzi dostajemy:

  • Name: DBA_Data
  • Physical_name:  H:\MSSQL\DATA\DBA_Data.ndf

Używając DBCC PAGE możemy odnaleźć identyfikator obiektu

/* 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 ('DBA',4, 50256,2);

Oglądając zrzut można odnaleźć ObcjectID oraz IndexID i za pomocą poniższego zapytania odszukujemy nazwę tabeli i indeksu.

USE DBA
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 = 92728981
    and si.index_id = 1;
GO

Tym samym możemy wyczytać na jakiej tabeli i jakim indeksie była blokada.

Key lock waits

Analogicznie gdy blokada występuje na poziomie klucza możemy rozkodować wpis

Przykładowo mamy

waitresource=“KEY: 8:72046656561991169 (cd54f92b253d)”

  • Identyfikator bazy – 8
  • Hobt_id = 72046656561991169
  • Wartość skrótu (cd54f92b253d)

Analogicznie jak poprzednio odnajdujemy nazwę bazy danych:

SELECT name
FROM sys.databases
WHERE database_id=8

Uzyskujemy np. DBA_Monitor

Hobt_id wyciągamy z sys.partitions

USE DBAMonitor
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 = 72046656561991169;

I można teraz wyciągnąć informację, że zapytanie było zablokowane przez tabelę cfg.Drivers a użyty był indeks PK_Drivers

Znając już nazwę tabeli można za pomocą nieudokumentowanego %%lockres%% znaleźć rekord , który spowodował blokadę.

SELECT  *
FROM cfg.Drivers (NOLOCK)
WHERE %%lockres%% = '(cd54f92b253d)';


Dariusz Brejnak

Od prawie trzydziestu lat jest pasjonatem informatyki, a zwłaszcza dziedzin dotyczących baz danych, hurtowni danych oraz ogólnie rozumianej tematyki BI. Jego druga pasja to fotografia http://dariuszbrejnak.pl