web-dev-qa-db-fra.com

Comment trouver ce qui verrouille mes tables

J'ai une table SQL qui ne peut tout à coup renvoyer de données à moins d'inclure "with (nolock)" à la fin, ce qui indique une sorte de verrou laissé sur ma table. J'ai un peu expérimenté avec dm_tran_locks pour identifier qu'il y avait en fait un certain nombre de verrous sur la table, mais comment puis-je identifier quoi les verrouille (c'est-à-dire l'élément request de dm_tran_locks)?

EDIT: Je connais sp_lock pour les versions antérieures à SQL 2005, mais maintenant que sp est obsolète, autant que je sache, c'est avec dm_tran_locks. J'utilise SQL Server 2008 R2.

38

Examinez les procédures stockées système suivantes, que vous pouvez exécuter dans SQLServer Management Studio (SSMS):

  • sp_who
  • sp_lock

En outre, dans SSMS, vous pouvez afficher les verrous et les processus de différentes manières:

enter image description here

Différentes versions de SSMS placent le moniteur d'activité à différents endroits. Par exemple, SSMS 2008 et 2012 l'ont dans le menu contextuel lorsque vous cliquez avec le bouton droit sur un nœud de serveur.

47
Nicholas Carey

Pour aller directement à "qui est bloqué/bloqué", j'ai combiné/abrégé sp_who et sp_lock en une seule requête qui donne une bonne vue d'ensemble de qui a quel objet est verrouillé à quel niveau.

--Create Procedure WhoLock
--AS
set nocount on
if object_id('tempdb..#locksummary') is not null Drop table #locksummary
if object_id('tempdb..#lock') is not null Drop table #lock
create table #lock (    spid int,    dbid int,    objId int,    indId int,    Type char(4),    resource nchar(32),    Mode char(8),    status char(6))
Insert into #lock exec sp_lock
if object_id('tempdb..#who') is not null Drop table #who
create table #who (     spid int, ecid int, status char(30),
            loginame char(128), hostname char(128),
            blk char(5), dbname char(128), cmd char(16)
            --
            , request_id INT --Needed for SQL 2008 onwards
            --
         )
Insert into #who exec sp_who
Print '-----------------------------------------'
Print 'Lock Summary for ' + @@servername  + ' (excluding tempdb):'
Print '-----------------------------------------' + Char(10)
Select     left(loginame, 28) as loginame, 
    left(db_name(dbid),128) as DB,
    left(object_name(objID),30) as object,
    max(mode) as [ToLevel],
    Count(*) as [How Many],
    Max(Case When mode= 'X' Then cmd Else null End) as [Xclusive lock for command],
    l.spid, hostname
into #LockSummary
from #lock l join #who w on l.spid= w.spid
where dbID != db_id('tempdb') and l.status='GRANT'
group by dbID, objID, l.spid, hostname, loginame

Select * from #LockSummary order by [ToLevel] Desc, [How Many] Desc, loginame, DB, object

Print '--------'
Print 'Who is blocking:'
Print '--------' + char(10)
SELECT p.spid
,convert(char(12), d.name) db_name
, program_name
, p.loginame
, convert(char(12), hostname) hostname
, cmd
, p.status
, p.blocked
, login_time
, last_batch
, p.spid
FROM      master..sysprocesses p
JOIN      master..sysdatabases d ON p.dbid =  d.dbid
WHERE     EXISTS (  SELECT 1
          FROM      master..sysprocesses p2
          WHERE     p2.blocked = p.spid )

Print '--------'
Print 'Details:'
Print '--------' + char(10)
Select     left(loginame, 30) as loginame,  l.spid,
    left(db_name(dbid),15) as DB,
    left(object_name(objID),40) as object,
    mode ,
    blk,
    l.status
from #lock l join #who w on l.spid= w.spid
where dbID != db_id('tempdb') and blk <>0
Order by mode desc, blk, loginame, dbID, objID, l.status

(Pour connaître la signification des abréviations du niveau de verrouillage, voir par exemple https://technet.Microsoft.com/en-us/library/ms175519%28v=sql.105%29.aspx )

Copié à partir de: sp_WhoLock - un proc stocké T-SQL combinant sp_who et sp_lock ...

NB: la colonne [Verrou exclusif pour la commande] peut être trompeuse - elle indique la commande en cours pour ce spid; mais le verrou X aurait pu être déclenché par une commande antérieure de la transaction.

46
Chris F Carroll

J'ai mis en place une procédure stockée qui traite non seulement des verrous et des blocages, mais aussi de voir ce qui est exécuté sur un serveur . , le code est ci-dessous:

USE [master]
go


CREATE PROCEDURE [dbo].[sp_radhe] 

AS
BEGIN

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


-- the current_processes
-- marcelo miorelli 
-- CCHQ 
-- 04 MAR 2013 Wednesday

SELECT es.session_id AS session_id
,COALESCE(es.original_login_name, '') AS login_name
,COALESCE(es.Host_name,'') AS hostname
,COALESCE(es.last_request_end_time,es.last_request_start_time) AS last_batch
,es.status
,COALESCE(er.blocking_session_id,0) AS blocked_by
,COALESCE(er.wait_type,'MISCELLANEOUS') AS waittype
,COALESCE(er.wait_time,0) AS waittime
,COALESCE(er.last_wait_type,'MISCELLANEOUS') AS lastwaittype
,COALESCE(er.wait_resource,'') AS waitresource
,coalesce(db_name(er.database_id),'No Info') as dbid
,COALESCE(er.command,'AWAITING COMMAND') AS cmd
,sql_text=st.text
,transaction_isolation =
CASE es.transaction_isolation_level
    WHEN 0 THEN 'Unspecified'
    WHEN 1 THEN 'Read Uncommitted'
    WHEN 2 THEN 'Read Committed'
    WHEN 3 THEN 'Repeatable'
    WHEN 4 THEN 'Serializable'
    WHEN 5 THEN 'Snapshot'
END
,COALESCE(es.cpu_time,0) 
    + COALESCE(er.cpu_time,0) AS cpu
,COALESCE(es.reads,0) 
    + COALESCE(es.writes,0) 
    + COALESCE(er.reads,0) 
+ COALESCE(er.writes,0) AS physical_io
,COALESCE(er.open_transaction_count,-1) AS open_tran
,COALESCE(es.program_name,'') AS program_name
,es.login_time
FROM sys.dm_exec_sessions es
LEFT OUTER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id
LEFT OUTER JOIN sys.dm_exec_requests er ON es.session_id = er.session_id
LEFT OUTER JOIN sys.server_principals sp ON es.security_id = sp.sid
LEFT OUTER JOIN sys.dm_os_tasks ota ON es.session_id = ota.session_id
LEFT OUTER JOIN sys.dm_os_threads oth ON ota.worker_address = oth.worker_address
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS st
where es.is_user_process = 1 
  and es.session_id <> @@spid
  and es.status = 'running'
ORDER BY es.session_id

end 

GO

cette procédure a très bien fonctionné pour moi ces dernières années . pour l'exécuter, tapez simplement sp_radhe

Concernant l'insertion de sp_radhe dans la base de données master

J'utilise le code suivant et en fais un procédure stockée système

exec sys.sp_MS_marksystemobject 'sp_radhe'

comme vous pouvez le voir sur le lien ci-dessous

Création de vos propres procédures stockées système SQL Server

Concernant le niveau d'isolation de la transaction

Questions sur les niveaux d'isolement des transactions T-SQL pour lesquelles vous étiez trop timide

Jonathan Kehayias

Une fois que vous avez modifié le niveau d'isolation de transaction, il ne change que lorsque l'étendue se termine à la fin de la procédure ou d'un appel de retour, ou si vous le modifiez à nouveau de manière explicite à l'aide de SET TRANSACTION ISOLATION LEVEL.

De plus, le NIVEAU TRANSACTION D'ISOLEMENT est limité au procédure stockée, vous pouvez donc avoir plusieurs procédures stockées imbriquées qui s'exécutent à leurs propres niveaux d'isolement.

12
marcello miorelli
exec sp_lock

Cette requête devrait vous donner des verrous existants. 

exec sp_who SPID -- will give you some info

Ayant des spids, vous pouvez consulter le moniteur d'activité (onglet des processus) pour savoir quels processus verrouillent les tables ("détails" pour plus d'informations et "kill processus" pour le tuer).

10
Li0liQ

Vous pouvez également utiliser sp_who2 qui donne plus d'informations 

Voici quelques informations http://dbadiaries.com/using-sp_who2-to-help-with-sql-server-troubleshooting

4
radar

Selon la documentation officielle, sp_lock est considéré comme obsolète:

Cette fonctionnalité est en mode maintenance et pourra être supprimée ultérieurement version de Microsoft SQL Server. Évitez d’utiliser cette fonctionnalité dans le nouveau fichier travaux de développement et envisagez de modifier les applications qui utilisent actuellement cette fonctionnalité.

et il est recommandé d'utiliser sys.dm_tran_locks à la place. Cet objet de gestion dynamique renvoie des informations sur les ressources du gestionnaire de verrouillage actuellement actives. Chaque ligne représente une demande active au gestionnaire de verrous pour un verrou qui a été accordé ou est en attente de l'être.

Il retourne généralement plus de détails dans une syntaxe plus conviviale que sp_lock.

La routine whoisactive écrite par Adam Machanic est très utile pour vérifier l'activité en cours dans votre environnement et voir quels types d'attentes/verrous ralentissent vos requêtes. Vous pouvez très facilement trouver ce qui bloque vos requêtes et de nombreuses autres informations utiles.


Par exemple, supposons que les requêtes suivantes soient exécutées dans le niveau d'isolation par défaut de SQL Server - Lecture validée. Chaque requête s'exécute dans une fenêtre de requête distincte:

-- creating sample data
CREATE TABLE [dbo].[DataSource]
(
    [RowID] INT PRIMARY KEY
   ,[RowValue] VARCHAR(12)
);

INSERT INTO [dbo].[DataSource]([RowID], [RowValue])
VALUES (1,  'samle data');

-- query window 1
BEGIN TRANSACTION;

    UPDATE [dbo].[DataSource]
    SET [RowValue] = 'new data'
    WHERE [RowID] = 1;

--COMMIT TRANSACTION;

-- query window 2
SELECT *
FROM [dbo].[DataSource];

Puis exécutez le sp_whoisactive (seule une partie des colonnes est affichée):

enter image description here

Vous pouvez facilement voir la session qui bloque l'instruction SELECT et même son code T-SQL. La routine a beaucoup de paramètres, vous pouvez donc vérifier le docs pour plus de détails.

Si nous interrogeons la vue sys.dm_tran_locks, nous pouvons voir que l'une des sessions attend le verrouillage de partage d'une ressource, qui dispose d'un verrouillage exclusif par une autre session:

enter image description here

0
gotqn