web-dev-qa-db-fra.com

Détection de la table ou de la ligne verrouillée dans SQL Server

J'essaie de comprendre/apprendre à retrouver les détails d'une session bloquée.

J'ai donc créé la configuration suivante:

create table foo (id integer not null primary key, some_data varchar(20));
insert into foo values (1, 'foo');
commit;

Maintenant, je me connecte deux fois à la base de données à partir de deux clients différents.

La première session émet:

begin transaction
update foo set some_data = 'update'
  where id = 1;

J'y fais explicitement pas afin de garder les verrous.

Dans la deuxième session, j'émets la même déclaration et bien sûr que l'on attend en raison du verrouillage. Maintenant, j'essaie d'utiliser les différentes requêtes flottantes pour voir que la session 2 attend la table foo.

sp_who2 montre ce qui suit (j'ai supprimé certaines colonnes pour n'afficher que les informations importantes):

 SPID | Statut | BlkBy | DBName | Commande | SPID | DEMANDÉ 
 ----- + -------------- + ------- + ---------- + ---- -------------- + ------ + ---------- 
 52 | dormir | . | foodb | EN ATTENTE DE COMMANDE | 52 | 0 
 53 | dormir | . | foodb | EN ATTENTE DE COMMANDE | 53 | 0 
 54 | SUSPENDU | 52 | foodb | MISE À JOUR | 54 | 0 
 56 | RUNNABLE | . | foodb | CHOISIR DANS | 56 | 0 

Cela est prévu, la session 54 est bloquée par les modifications non validées de la session 52.

Requête sys.dm_os_waiting_tasks le montre également. La déclaration:

select session_id, wait_type, resource_address, resource_description
from sys.dm_os_waiting_tasks
where blocking_session_id is not null;

retour:

 session_id | wait_type | adresse_ressource | description_ressource 
 ----------- + ----------- + -------------------- + ------------------------------------------------- -------------------------------- 
 54 | LCK_M_X | 0x000000002a35cd40 | hobtid de verrouillage = 72057594046054400 dbid = 6 id = mode lock4ed1dd780 = X associatedObjectId = 72057594046054400 

Encore une fois, cela est attendu.

Mon problème est que je ne peux pas trouver comment trouver le nom d'objet réel que la session 54 attend.

J'ai trouvé plusieurs requêtes qui rejoignent sys.dm_tran_locks et sys.dm_os_waiting_tasks comme ça:

SELECT ....
FROM sys.dm_tran_locks AS l
  JOIN sys.dm_os_waiting_tasks AS wt ON wt.resource_address = l.lock_owner_address

Mais dans mon scénario de test ci-dessus, cette jointure ne renvoie rien. Donc, cette jointure est incorrecte ou dm_tran_locks ne contient pas réellement les informations que je recherche.

Donc ce que je recherche, c'est une requête qui renvoie quelque chose comme:
" la session 54 attend un verrou dans la table foo".


Quelques informations de fond:

Le problème réel que j'essaie de résoudre est un peu plus compliqué, mais se résume à la question "sur quelle table la session 54 attend-elle". Le problème en question implique une procédure stockée de grande taille qui met à jour plusieurs tables et une sélection dans une vue qui accède à certaines de ces tables. L'instruction select est bloquée même si l'isolement de l'instantané et la lecture de l'instantané validé sont activés. Déterminer pourquoi la sélection est bloquée (ce que je pensais ne serait pas possible si l'isolement de l'instantané est activé) sera la prochaine étape.

Dans un premier temps, j'aimerais savoir ce que cette session attend.

20

Je pense que cela fait ce dont vous avez besoin.

USE 'yourDB'
GO
SELECT  
    OBJECT_NAME(p.[object_id]) BlockedObject
FROM    sys.dm_exec_connections AS blocking
    INNER JOIN sys.dm_exec_requests blocked
        ON blocking.session_id = blocked.blocking_session_id
    INNER JOIN sys.dm_os_waiting_tasks waitstats
        ON waitstats.session_id = blocked.session_id
    INNER JOIN sys.partitions p ON SUBSTRING(resource_description, 
        PATINDEX('%associatedObjectId%', resource_description) + 19, 
        LEN(resource_description)) = p.partition_id
23
James Anderson

Tu peux l'essayer :

SELECT 
db_name(rsc_dbid) AS 'DATABASE_NAME',
case rsc_type when 1 then 'null'
              when 2 then 'DATABASE' 
              WHEN 3 THEN 'FILE'
              WHEN 4 THEN 'INDEX'
              WHEN 5 THEN 'TABLE'
              WHEN 6 THEN 'PAGE'
              WHEN 7 THEN 'KEY'
              WHEN 8 THEN 'EXTEND'
              WHEN 9 THEN 'RID ( ROW ID)'
              WHEN 10 THEN 'APPLICATION' end  AS 'REQUEST_TYPE',

CASE req_ownertype WHEN 1 THEN 'TRANSACTION'
                   WHEN 2 THEN 'CURSOR'
                   WHEN 3 THEN 'SESSION'
                   WHEN 4 THEN 'ExSESSION' END AS 'REQUEST_OWNERTYPE',

OBJECT_NAME(rsc_objid ,rsc_dbid) AS 'OBJECT_NAME', 
PROCESS.HOSTNAME , 
PROCESS.program_name , 
PROCESS.nt_domain , 
PROCESS.nt_username , 
PROCESS.program_name ,
SQLTEXT.text 
FROM sys.syslockinfo LOCK JOIN 
     sys.sysprocesses PROCESS
  ON LOCK.req_spid = PROCESS.spid
CROSS APPLY sys.dm_exec_sql_text(PROCESS.SQL_HANDLE) SQLTEXT
3
Amin Attarzadeh