Décryptage des Key et Page WaitResource dans les blocages et deadlocks

Si vous utilisez le rapport sur les blocages (blocked process report) ou collectez des graphiques de blocage fournis par SQL Server, vous rencontrerez parfois des éléments tels que :

waitresource="PAGE: 6:3:70133"

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

Parfois, dans ce gigantesque XML que vous étudiez, il y aura plus d'informations (les graphiques de blocage contiennent une liste de ressources qui aide à identifier les noms des objets et des index), mais ce n'est pas toujours le cas.

Ce texte vous aidera à les décoder.

Toutes les informations présentes ici sont sur Internet à divers endroits, elles sont simplement trÚs dispersées ! Je veux rassembler tout cela - de DBCC PAGE à hobt_id et aux fonctions non documentées %%physloc%% et %%lockres%%.

D'abord, parlons des attentes sur les blocages PAGE, puis passons aux blocages KEY.

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

Si votre requĂȘte attend un blocage PAGE, SQL Server vous donnera l'adresse de cette page.

En décomposant «PAGE: 6:3:70133», nous obtenons :

  • database_id = 6
  • data_file_id = 3
  • page_numer = 70133

1.1) Décodons database_id

Trouvons le nom de la base de donnĂ©es avec la requĂȘte :

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

C'est une base de données publique WideWorldImporters sur mon SQL Server.

1.2) Recherche du nom du fichier de données - si cela vous intéresse

Nous allons utiliser data_file_id Ă  l'Ă©tape suivante pour trouver le nom de la table. Vous pouvez simplement passer Ă  l'Ă©tape suivante, mais si vous ĂȘtes intĂ©ressĂ© par le nom du fichier, vous pouvez le trouver en exĂ©cutant une requĂȘte dans le contexte de la base de donnĂ©es trouvĂ©e, en substituant data_file_id dans cette requĂȘte :

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

Dans la base de donnĂ©es WideWorldImporters, ce fichier est nommĂ© WWI_UserData et il est restaurĂ© chez moi dans C:MSSQLDATAWideWorldImporters_UserData.ndf. (Oups, vous m'avez pris en train de mettre des fichiers sur un disque systĂšme ! Non ! Ça a mal tournĂ©).

1.3) Obtenir le nom de l'objet Ă  partir de DBCC PAGE

Maintenant, nous savons que la page #70133 dans le fichier de données 3 appartient à la base de données WorldWideImporters. Nous pouvons examiner le contenu de cette page en utilisant DBCC PAGE non documenté et le trace flag 3604.
Remarque : je préfÚre utiliser DBCC PAGE sur une copie récupérée à partir d'une sauvegarde quelque part sur un autre serveur, car c'est une chose non documentée. Dans certains cas, cela peut entraßner la création d'un dump (Note du traducteur - le lien mÚne malheureusement nulle part, mais d'aprÚs l'url, il s'agit d'index filtrés).

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

En consultant les résultats, on peut trouver object_id et index_id.
Décryptage des Key et Page WaitResource dans les blocages et deadlocks
Presque prĂȘt ! Vous pouvez maintenant trouver les noms de table et d'index Ă  l'aide de la requĂȘte :

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

Et nous pouvons voir que l'attente sur le verrou était sur l'index PK_Sales_OrderLines de la table Sales.OrderLines.

Remarque : dans SQL Server 2014 et version ultĂ©rieure, le nom de l'objet peut Ă©galement ĂȘtre trouvĂ© Ă  l'aide de la DMO non documentĂ©e sys.dm_db_database_page_allocations. Mais vous devrez interroger chaque page dans la base de donnĂ©es, ce qui n'est pas trĂšs Ă©lĂ©gant pour les grandes bases de donnĂ©es, c'est pourquoi j'ai utilisĂ© DBCC PAGE.

1.4) Peut-on voir les données à la page qui a été verrouillée ?

Eh bien, oui. Mais
 ĂȘtes-vous sĂ»rs que c’est vraiment ce dont vous avez besoin ?
C'est lent mĂȘme sur de petites tables. Mais c'est plutĂŽt amusant, donc, puisque vous avez lu jusqu'ici
 parlons de %%physloc%% !

%%physloc%% est un morceau non documenté de magie qui retourne l'identifiant physique pour chaque enregistrement. Vous pouvez utiliser %%physloc%% avec sys.fn_PhysLocFormatter dans SQL Server 2008 et version ultérieure.

Maintenant que nous savons que nous voulions verrouiller la page dans Sales.OrderLines, nous pouvons voir toutes les donnĂ©es dans cette table, qui sont stockĂ©es dans le fichier de donnĂ©es #3 Ă  la page #70133, Ă  l'aide de cette requĂȘte :

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

Comme je l'ai dit, c'est lent mĂȘme sur de minuscules tables. J'ai ajoutĂ© NOLOCK Ă  la requĂȘte car nous n'avons de toute façon aucune garantie que les donnĂ©es sur lesquelles nous voulons jeter un coup d'Ɠil sont exactement les mĂȘmes que celles qui Ă©taient prĂ©sentes au moment oĂč le verrou a Ă©tĂ© dĂ©couvert — donc nous pouvons faire des lectures non fiables.
Mais, hourra, la requĂȘte me retourne ces 25 lignes pour lesquelles notre requĂȘte a luttĂ©.
Décryptage des Key et Page WaitResource dans les blocages et deadlocks
Assez parlé des verrous PAGE. Que se passe-t-il si nous attendons un verrou KEY ?

2) waitresource=“KEY: 6:72057594041991168 (ce52f92a058c)” = Database_Id, HOBT_Id (le hachage magique qui peut ĂȘtre dĂ©chiffrĂ© Ă  l'aide de %%lockres%%, si vous le souhaitez vraiment)

Si votre requĂȘte tente de verrouiller une ligne dans l'index et se retrouve elle-mĂȘme bloquĂ©e, vous obtenez un type d'adresse complĂštement diffĂ©rent.
En dĂ©composant “6:72057594041991168 (ce52f92a058c)” en parties, nous obtenons :

  • database_id = 6
  • hobt_id = 72057594041991168
  • hachage magique = (ce52f92a058c)

2.1) Déchiffrons database_id

Cela fonctionne exactement de la mĂȘme façon que dans l'exemple ci-dessus ! Trouvons le nom de la base de donnĂ©es grĂące Ă  la requĂȘte :

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

Dans mon cas, c'est toujours la mĂȘme WideWorldImporters.

2.2) Déchiffrons hobt_id

Dans le contexte de la base de donnĂ©es trouvĂ©e, il faut exĂ©cuter une requĂȘte Ă  sys.partitions avec quelques jointures qui aideront Ă  dĂ©terminer les noms de la table et de l'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

Il me dit que la requĂȘte Ă©tait en attente sur le verrou Application.Countries, utilisant l'index PK_Application_Countries.

2.3) Maintenant un peu de magie %%lockres%% — si vous voulez dĂ©terminer quel enregistrement a Ă©tĂ© verrouillĂ©

Si je veux vraiment savoir sur quelle ligne le verrou Ă©tait nĂ©cessaire, je peux le dĂ©couvrir grĂące Ă  une requĂȘte sur la table elle-mĂȘme. Nous pouvons utiliser la fonction non documentĂ©e %%lockres%% pour trouver l'enregistrement correspondant au hash magique.
Notez que cette requĂȘte va scanner toute la table, et sur de grandes tables, cela peut ne pas ĂȘtre trĂšs agrĂ©able :

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

J'ai ajoutĂ© NOLOCK (sur les conseils de Klaus Aschenbrenner sur Twitter) car les verrous peuvent devenir un problĂšme. Nous voulons juste jeter un Ɠil Ă  ce qu'il y a maintenant, et non Ă  ce qu'il y avait quand la transaction a commencĂ© — je ne pense pas que la cohĂ©rence des donnĂ©es nous importe.
VoilĂ , l'enregistrement pour lequel nous nous sommes battus !
Décryptage des Key et Page WaitResource dans les blocages et deadlocks

Remerciements et lectures supplémentaires

Je ne me souviens pas qui a décrit pour la premiÚre fois beaucoup de ces choses, mais voici deux articles sur les éléments les moins documentés que vous pourriez apprécier :

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster