2011-01-05 13 views
1

Ich habe CTEs, die alle NOLOCK innen verwendet. Aber dann wählt aus diesen CTEs in Eltern-CTEs mit Kindern CTEs nicht NOLOCK in der Annahme, dass es bereits NOLOCK'd ist. Und die letzte Auswahl verwendet NOLOCK auch nicht.SQL Server 2008: Wie funktioniert NOLOCK für CTE?

So etwas:

with cte1 as 
(select * from tab1 (nolock)), 
cte2 as 
(select * from cte1) 

select * from cte2 

oder soll ich schreiben

with cte1 as 
(select * from tab1 (nolock)), 
cte2 as 
(select * from cte1 (nolock)) 

select * from cte2 (nolock) 

dank

+1

Ich würde SELECT nicht verwenden * 'oder' NOLOCK' überhaupt. Da CTEs ab SQL 2005 unterstützt werden, gibt es bessere Möglichkeiten, sicherzustellen, dass Sie festgeschriebene, aber historische Daten lesen als NOLOCK. –

+0

Ich möchte nicht lange laufen Bericht einen Tisch zu sperren .. was meine anderen Optionen sind? –

Antwort

4

Sie brauchen nicht die äußere nolock gemeinsame Sperren auf tab1 Einnahme zu vermeiden. Sie können dies leicht überprüfen, indem Sie eine SQL Profiler-Ablaufverfolgung einrichten, die die verschiedenen Ereignisse in der Kategorie locks erfasst, auf dem Spid einer SSMS-Verbindung filtert und beide Versionen ausprobiert.

nolock ist eine ziemlich gefährliche Einstellung, aber sind Ihnen alle möglichen Nachteile bekannt, diese zu nutzen (Dirty Reads, Lesen von Daten zweimal oder gar nicht)?

+2

+1 Wusste nicht, dass Sie Sperren mit dem Profiler überwachen können. – Andomar

+0

ja ich bin mir bewusst. Danke –

1

Die innerste nolock ausreichend ist, keine Notwendigkeit, sie für die äußeren wählt zu wiederholen.

Sie können dies testen, indem Sie eine Transaktion starten, ohne sie zu beenden:

begin transaction 
; with YourCte (... 

Dann können Sie die Schlösser mit Management Studio sehen. Sie werden dort sein, bis die Transaktion ausläuft.

+0

Hängt von der Isolationsstufe ab. Gemeinsame Sperren werden normalerweise freigegeben, sobald die Daten gelesen werden. –

2

NOLOCK auf einer „äußeren“ Abfrage gilt für alle zu inneren Abfragen. Ein CTE ist nur ein Makro wie eine Ansicht oder Inline-Tabelle udf: nicht mehr und nicht weniger. So haben Sie eigentlich (NOLOCK Hinweise zu ignorieren)

select * from (
       select * from (
          select * from tab1 
          ) t1 
       ) t2 

Von Table Hints on MSDN unter „Bemerkungen“

Alle Hinweise sperren propagiert werden auf alle Tabellen und Views, die von der Abfrage-Plan zugegriffen werden, einschließlich Tabellen und Ansichten, auf die in einer Ansicht verwiesen wird.

In diesem Fall benötigen Sie nur einen. Egal wo.

Wo es wichtig ist, ist, wo Sie JOINs haben. Wenn cte1 eine Verknüpfung von 2 Tabellen wäre, würden Sie sie für jede Tabelle benötigen. Oder spezifizieren Sie es einmal auf einer höheren/äußeren Ebene.

Oh, und ich werde mit allen anderen mitmachen: NOLOCK is a bad idea

+0

Vielen Dank für die Referenzierung der Dokumentation. Ich denke, das sollte die akzeptierte Antwort sein! – chrnola