Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Was hindert Select top 1 * from TableName with (nolock) daran, ein Ergebnis zurückzugeben?

SELECT Abfragen mit NOLOCK Nehmen Sie eigentlich keine Schlösser, sie brauchen immer noch ein SCH-S (Schema-Stabilität) Sperre auf dem Tisch (und wie es ist ein heap wird auch ein hobt benötigt sperren ).

Zusätzlich vor dem SELECT SQL Server kann sogar beginnen, muss einen Plan für die Anweisung kompilieren, was auch erfordert, dass er ein SCH-S nimmt den Tisch aussperren.

Da Ihre lang laufende Transaktion die Tabelle über SELECT ... INTO erstellt es enthält einen inkompatiblen SCH-M Sperren Sie es, bis die Anweisung abgeschlossen ist.

Sie können dies überprüfen, indem Sie in sys.dm_os_waiting_tasks nachsehen während während während der Sperrfrist.

Als ich das Folgende in einer Verbindung versuchte

BEGIN TRAN

SELECT *
INTO NewT
FROM master..spt_values

/*Remember to rollback/commit this later*/

Und dann ausführen (oder einfach nur versuchen, den geschätzten Ausführungsplan anzuzeigen)

SELECT *
FROM NewT
WITH (NOLOCK)

in einer Sekunde wurde die Leseabfrage blockiert.

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

Zeigt, dass der Wartetyp tatsächlich SCH_S ist und die blockierende Ressource 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