Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Qu'est-ce qui empêche Select top 1 * de TableName avec (nolock) de renvoyer un résultat ?

SELECT requêtes avec NOLOCK ne prenez pas de verrous, ils ont toujours besoin d'un SCH-S (stabilité du schéma) verrou sur la table (et comme il s'agit d'un tas il faudra aussi un hobt verrouiller ).

De plus avant le SELECT peut même commencer SQL Server doit compiler un plan pour l'instruction, ce qui nécessite également qu'il prenne un SCH-S verrouiller sur la table.

Comme votre longue transaction crée la table via SELECT ... INTO il contient un SCH-M incompatible verrouillez-le jusqu'à ce que l'instruction soit terminée.

Vous pouvez le vérifier en regardant dans sys.dm_os_waiting_tasks pendant pendant pendant la période de blocage.

Lorsque j'ai essayé ce qui suit dans une connexion

BEGIN TRAN

SELECT *
INTO NewT
FROM master..spt_values

/*Remember to rollback/commit this later*/

Et puis exécuter (ou simplement essayer de voir le plan d'exécution estimé)

SELECT *
FROM NewT
WITH (NOLOCK)

en une seconde, la requête de lecture a été bloquée.

SELECT wait_type,
       resource_description
FROM sys.dm_os_waiting_tasks
WHERE session_id = <spid_of_waiting_task>

Montre que le type d'attente est bien SCH_S et la ressource bloquante SCH-M

wait_type        resource_description
---------------- -------------------------------------------------------------------------------------------------------------------------------
LCK_M_SCH_S      objectlock lockPartition=0 objid=461960722 subresource=FULL dbid=1 id=lock4a8a540 mode=Sch-M associatedObjectId=461960722