Afficher les verrous acquis lors de l'exécution des requêtes (SQL Server)

12

Le plan d'exécution de la requête n'affiche pas les détails de verrouillage par défaut, est-il possible de visualiser les verrous, ainsi que le type, acquis lors de l'exécution d'une requête?

Faisal Mansoor
la source

Réponses:

14

est-il possible de visualiser les verrous, ainsi que le type, acquis lors de l'exécution d'une requête?

Oui, pour déterminer les verrous,

  1. Vous pouvez utiliser beta_lockinfopar Erland Sommarskog

    beta_lockinfoest une procédure stockée qui fournit des informations sur les processus et les verrous qu'ils détiennent ainsi que leurs transactions actives. beta_lockinfoest conçu pour collecter autant d'informations que possible sur une situation de blocage, afin que vous puissiez instantanément trouver le coupable et tuer le processus de blocage si la situation est désespérée. Ensuite, vous pouvez vous asseoir et analyser la sortie de beta_lockinfopour comprendre comment la situation de blocage s'est produite et déterminer les actions à entreprendre pour éviter que la situation ne se reproduise. La sortie de beta_lockinfomontre tous les processus actifs ainsi que les processus passifs avec des verrous, quels objets ils verrouillent, quelle commande ils ont soumise en dernier et quelle instruction ils exécutent. Vous obtenez également les plans de requête pour les instructions en cours. Normalement, vous exécutezbeta_lockinfopour regarder directement la sortie, mais il existe également un mode d'archivage où les données sont enregistrées dans la table. Ce n'est pas le moins utile, si vous voulez que quelqu'un vous envoie la sortie d' beta_lockinfoun site auquel vous n'avez pas accès.

  2. Une autre méthode consiste à utiliser sp_whoIsActivepar Adam Machanic avec@get_locks = 1

    EXEC sp_WhoIsActive 
    @filter = '', 
    @filter_type = 'session', 
    @not_filter = '', 
    @not_filter_type = 'session', 
    @show_own_spid = 0, 
    @show_system_spids = 0, 
    @show_sleeping_spids = 1, 
    @get_full_inner_text = 0, 
    @get_plans = 1, 
    @get_outer_command = 1, 
    @get_transaction_info = 0, 
    @get_task_info = 1, 
    @get_locks = 1,   ----------> 1 = ON (get lock info); 0 = OFF
    @get_avg_time = 0, 
    @get_additional_info = 0, 
    @find_block_leaders = 0, 
    @delta_interval = 0, 
    @output_column_list = '[dd%][session_id][sql_text][sql_command][login_name][wait_info][tasks][tran_log%][cpu%][temp%][block%][reads%][writes%][context%][physical%][query_plan][locks][%]', 
    @sort_order = '[start_time] ASC', 
    @format_output = 1, 
    @destination_table = '', 
    @return_schema = 0, 
    @schema = NULL, 
    @help = 0
Kin Shah
la source
merci, les procs stockés ci-dessus sont parfaits pour les scénarios d'administration db, mais connaissez-vous des alternatives pour les scénarios d'optimisation des requêtes. J'essaie de comprendre le comportement de verrouillage d'une requête d'insertion dans un environnement de développement (qui n'a pas beaucoup de données, donc la requête ne s'exécute pas très longtemps). Je voudrais voir tous les verrous acquis par une requête après son exécution, je suis intéressé à voir le plan de verrouillage, similaire au fonctionnement du plan de requête.
Faisal Mansoor
1
Étant donné que vous utilisez SQL Server 2012, au niveau granulaire des requêtes, vous devez examiner XEvents - Déterminer quelles requêtes contiennent des verrous . Cela vous donnera un bon départ.
Kin Shah
4

Voici comment je regarde les verrous par type de processus / table / verrou:

SELECT 
    HostName,
    "OS UserName",
    Login, 
    spid, 
    "Database", 
    TableID,
    "Table Name_________", 
    IndID, 
--  [Index Name],
    "Lock Type", 
    "Lock Mode", 
    Status, 
--  Resource,
    Count(*) AS "Lock Count"
FROM (
    SELECT
        Convert(VarChar(30), RTRIM(P.HostName)) AS HostName,
        Convert(VarChar(30), RTRIM(P.nt_UserName)) AS "OS UserName",
        Convert(VarChar(30), Suser_SName(p.sid)) AS Login, 
        Convert(SmallInt, req_spid) AS spid,
        Convert(VarChar(30), DB_Name(rsc_dbid)) AS "Database",
        rsc_objid AS TableID,
    Convert(VarChar(30), Object_Name(rsc_objid, rsc_dbid))
        AS [Table Name_________],
        rsc_indid AS IndID, 
        CASE SubString (lock_type.name, 1, 4) 
            When '' Then 'None'
            When 'DB' Then 'Database'
            When 'FIL' Then 'File'
            When 'IDX' Then 'Index'
            When 'TAB' Then 'Table'
            When 'PAG' Then 'Page'
            When 'KEY' Then 'Key'
            When 'EXT' Then 'Extent'
            When 'RID' Then 'Row ID'
            When 'APP' Then 'Application'
            Else SubString (lock_type.name, 1, 4)
        END AS "Lock Type",
        Case SubString (lock_mode.name, 1, 12)
            When NULL Then 'N/A'
            When 'Sch-S' Then 'SCHEMA (Stability)'--'SCHEMA stability lock'
            When 'Sch-M' Then 'SCHEMA (Modification)'--'SCHEMA modification lock'
            When 'S' Then 'SHARED'--'SHARED Lock acquisition'
            When 'U' Then 'UPDATE'--'UPDATE lock acquisition'
            When 'X' Then 'EXCLUSIVE'--'EXCLUSIVE lock granted'
            When 'IS' Then 'SHARED (Intent)'--'INTENT for SHARED lock'
            When 'IU' Then 'UPDATE (Intent)'--'INTENT for UPDATE lock'
            When 'IX' Then 'EXCLUSIVE (Intent)'--'INTENT for EXCLUSIVE lock'
            When 'SIU' Then 'SHARED (Intent UPDATE)'--'SHARED lock with INTENT for UPDATE'
            When 'SIX' Then 'SHARED (Intent EXCLUSIVE)'--'SHARED lock with INTENT for EXCLUSIVE'
            When 'UIX' Then 'UPDATE'--'UPDATE lock with INTENT for EXCLUSIVE'
            When 'BU' Then 'UPDATE (BULK)'--'BULK UPDATE lock'
            Else SubString (lock_mode.name, 1, 12)
        END AS "Lock Mode", 
        SubString(lock_status.name, 1, 5) AS Status,
        SubString (rsc_text, 1, 16) AS Resource
    FROM 
        Master..SysLockInfo S
        JOIN Master..spt_values lock_type on S.rsc_type = lock_type.number
        JOIN Master..spt_values lock_status on S.req_status = lock_status.number
        JOIN Master..spt_values lock_mode on S.req_mode = lock_mode.number -1
        JOIN Master..SysProcesses P on S.req_spid = P.spid
    WHERE
            lock_type.type = 'LR'
        AND lock_status.type = 'LS'
        AND lock_mode.type = 'L'
        AND DB_Name(rsc_dbid) NOT IN ('master', 'msdb', 'model')
    ) AS X
WHERE TableID > 0
GROUP BY 
    HostName,
    "OS UserName",
    Login, 
    spid, 
    "Database", 
    TableID,
    "Table Name_________", 
    IndID, 
    "Lock Type", 
    "Lock Mode", 
    Status
ORDER BY
    spid, "Database", "Table Name_________", "Lock Type", Login
Shane Estelle
la source
3
C'est une excellente réponse et c'est tellement dommage qu'il utilise des vues de compatibilité. Allez, c'est 2015!
spaghettidba
3

Vous pouvez afficher l'historique des verrous acquis dans l'onglet "Messages" après avoir exécuté ceci: DBCC TRACEON (1200, 3604, -1) Mais ATTENTION, il active GLOBALEMENT ces indicateurs de trace, alors n'oubliez pas de les désactiver dès que vous ne le faites pas besoin d'eux.

Vedran
la source
1

Vous pouvez afficher les verrous d'une session à l'aide de sp_lock ou sys.dm_tran_locks. Dans les deux cas, vous pouvez filtrer par session. Vous pouvez également utiliser des événements étendus pour ce faire.

Matan Yungman
la source
0

Oui, vous pouvez afficher les verrous et leur type lors de l'exécution de la requête via

  1. Adam Mechanics's SP_whoisactive cliquez ici pour voir

  2. De plus, si vous souhaitez créer un rapport de bloc avec vous pouvez le faire avec l'aide de la trace comme expliqué ici

KASQLDBA
la source
1
performance countersvous donnera simplement un comportement à l'échelle de l'instance. L'OP veut au niveau de la requête.
Kin Shah
@Kin, merci, vient de supprimer les informations supplémentaires :)
KASQLDBA