{"id":232,"date":"2011-05-07T00:00:10","date_gmt":"2011-05-07T00:00:10","guid":{"rendered":"http:\/\/www.sqlserver.fr\/blog\/?p=232"},"modified":"2020-09-01T10:07:52","modified_gmt":"2020-09-01T08:07:52","slug":"sys-dm_tran_locks-partie-2","status":"publish","type":"post","link":"https:\/\/www.sqlserver.fr\/blog\/sys-dm_tran_locks-partie-2\/","title":{"rendered":"Gestion des verrous (Partie 2)"},"content":{"rendered":"<p>Dans un pr\u00e9c\u00e9dent article (voir <a href=\"https:\/\/www.sqlserver.fr\/blog\/sys-dm_tran_locks-partie-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">ici<\/a>), j\u2019ai pr\u00e9sent\u00e9 une premi\u00e8re approche d\u2019un usage de la vue sys.dm_tran_locks afin d\u2019identifier dans le cas des verrous de type PAGE les donn\u00e9es concern\u00e9es par le verrouillage.<br \/>\nMaintenant, attachons-nous \u00e0 l\u2019identification plus pr\u00e9cise des lignes de donn\u00e9es verrouill\u00e9es, c\u2019est-\u00e0-dire aux verrous de type KEY.<!--more--><br \/>\nPour rappel, le niveau de verrouillage des ressources dans SQL Server se fait suivant plusieurs niveaux hi\u00e9rarchiques, d\u00e9taill\u00e9s ici : <a href=\"https:\/\/docs.microsoft.com\/fr-fr\/previous-versions\/sql\/sql-server-2008-r2\/ms189849(v=sql.105)\">https:\/\/docs.microsoft.com\/fr-fr\/previous-versions\/sql\/sql-server-2008-r2\/ms189849(v=sql.105)<\/a>.<br \/>\nLes verrous de ligne sont identifi\u00e9s dans la vue sys.dm_tran_locks par l\u2019identifiant de la partition concern\u00e9es (de m\u00eame que les verrous de niveau PAGE) mais surtout par une valeur de hachage (KeyHashValue) qui permet au syst\u00e8me d\u2019identifier rapidement la ligne sur laquelle porte le verrou.<br \/>\nPar exemple, posons un verrou sur une ligne donn\u00e9e dans la table Sales.SalesOrderDetail (la transaction restant ouverte, le verrou n\u2019est pas lib\u00e9r\u00e9).<br \/>\n<span style=\"font-family: 'courier new', courier;\">\/*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> begin transaction<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> select top 1 SalesOrderDetailID,rowguid<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> from Sales.SalesOrderDetail with (rowlock, xlock)<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> order by rowguid desc<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;*\/<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> SalesOrderDetailID rowguid<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> &#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> 18519 7762B051-2A02-4488-A42D-FFFF46488486<\/span><br \/>\nCherchons, depuis cette connexion (et donc \u00e0 l\u2019int\u00e9rieur de cette transaction) \u00e0 v\u00e9rifier qu\u2019un verrou est bien en place sur la ligne :<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0012.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-235\" title=\"image001\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0012.jpg\" alt=\"\" width=\"604\" height=\"113\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0012.jpg 604w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0012-300x56.jpg 300w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><\/a><\/p>\n<p>Nous constatons notamment un verrou exclusif (request_mode=\u2019X\u2019) sur une ligne (resource_type=\u2019KEY\u2019). Les valeurs nous permettant d\u2019identifier la ressource concern\u00e9e sont dans un premier temps resource_associated_entity_id, qui correspond \u00e0 l\u2019identifiant HoBT (Heap or B-Tree) dans la table sys.partitions.<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0021.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-236\" title=\"image002\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0021.jpg\" alt=\"\" width=\"604\" height=\"140\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0021.jpg 604w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image0021-300x69.jpg 300w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><\/a><\/p>\n<p>Nous constatons bien que nous somme dans la bonne table (Sales.SalesOrderDetail), et qui plus est que nous avons interrog\u00e9 cette table \u00e0 travers l\u2019index portant sur rowguid.<br \/>\nReste maintenant \u00e0 identifier LA ligne concern\u00e9e par ce verrou. Cela se fait \u00e0 partir de la valeur de hachage (3e6e808d7855). Nous voyons d\u00e9j\u00e0, \u00e0 travers le verrou de page pos\u00e9, que nous sommes dans la page 1:17648. Nous pouvons donc d\u00e9j\u00e0, comme \u00e9voqu\u00e9 dans mon <a href=\"https:\/\/www.sqlserver.fr\/blog\/sys-dm_tran_locks-partie-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">pr\u00e9c\u00e9dent article<\/a>, utiliser la commande DBCC PAGE.<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image003.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-237\" title=\"image003\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image003.jpg\" alt=\"\" width=\"604\" height=\"585\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image003.jpg 604w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image003-300x290.jpg 300w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><\/a><\/p>\n<p>La derni\u00e8re ligne correspond bien \u00e0 l\u2019enregistrement que nous avons verrouill\u00e9.<br \/>\nA noter toutefois que la recherche du KeyHashValue manuellement dans le r\u00e9sultat de DBCC PAGE n\u2019est pas tr\u00e8s \u00ab industrielle \u00bb. Plusieurs autres m\u00e9thodes de recherche existent, mais la plus simple est l\u2019utilisation d\u2019une colonne cach\u00e9e nomm\u00e9e %%lockres%%, qui contient ligne par ligne la cl\u00e9 de hachage correspondante.<br \/>\n<span style=\"font-family: 'courier new', courier;\">\/*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> select rowguid,SalesOrderDetailID,%%lockres%% as HashKeyValue<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> from sales.SalesOrderDetail with (nolock,index(AK_SalesOrderDetail_rowguid))<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> where (%%lockres%%)='(3e6e808d7855)&rsquo;<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;*\/<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> rowguid SalesOrderDetailID HashKeyValue<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> 7762B051-2A02-4488-A42D-FFFF46488486 18519 (3e6e808d7855)<\/span><br \/>\nRemarque importante \u00e0 bien prendre en compte, la cl\u00e9 de hachage d\u00e9pend de l\u2019index utilis\u00e9. Ainsi, la requ\u00eate suivante donnera une autre cl\u00e9 de hachage car elle s\u2019appuiera sur un autre index :<br \/>\n<span style=\"font-family: 'courier new', courier;\">\/*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> select rowguid,SalesOrderDetailID,%%lockres%% as HashKeyValue<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> from sales.SalesOrderDetail with (nolock)<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> where SalesOrderDetailID=18519<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;*\/<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> rowguid SalesOrderDetailID HashKeyValue<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<\/span><br \/>\n<span style=\"font-family: 'courier new', courier;\"> 7762B051-2A02-4488-A42D-FFFF46488486 18519 (e2f0aa5e3af2)<\/span><\/p>\n<p>Voil\u00e0 pour un bref exemple pr\u00e9sentant la recherche des enregistrements partie prenante dans un verrou. N\u2019h\u00e9sitez pas \u00e0 me donner votre avis sur cet article o\u00f9 \u00e0 poser un commentaire pour toute question compl\u00e9mentaire\u2026<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dans un pr\u00e9c\u00e9dent article (voir ici), j\u2019ai pr\u00e9sent\u00e9 une premi\u00e8re approche d\u2019un usage de la vue sys.dm_tran_locks afin d\u2019identifier dans le cas des verrous de type PAGE les donn\u00e9es concern\u00e9es par le verrouillage. Maintenant, attachons-nous \u00e0 l\u2019identification plus pr\u00e9cise des &hellip; <a href=\"https:\/\/www.sqlserver.fr\/blog\/sys-dm_tran_locks-partie-2\/\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-232","post","type-post","status-publish","format-standard","hentry","category-article_sql"],"_links":{"self":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/232","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/comments?post=232"}],"version-history":[{"count":17,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/232\/revisions"}],"predecessor-version":[{"id":1827,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/232\/revisions\/1827"}],"wp:attachment":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/media?parent=232"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/categories?post=232"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/tags?post=232"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}