2011-01-05 26 views
1

私はすべてがNOLOCKを内部で使用するCTEを持っています。しかし、子CTEを使用している親CTE内のそれらのCTEから、既にNOLOCKされていると仮定してNOLOCKを使用しないことを選択する。最後の選択でもNOLOCKは使用されません。そのようなSQL Server 2008:CTEでNOLOCKはどのように機能しますか?

何か:

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

select * from cte2 

または私はあなたがtab1に共有ロックを取って回避するために、外側のnolockを必要としない

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

select * from cte2 (nolock) 

おかげ

+1

私はすべて* 'や' NOLOCK'をSELECT '使用することはありません。 CTEがSQL 2005以上でサポートされていることを確認すると、NOLOCKよりもコミットされたが履歴データを確実に読み取るためのより良い方法があります。 –

+0

私は長時間実行しているレポートがテーブルをロックしないようにしたいのですが、私の他のオプションは何ですか? –

答えて

4

を書くものとします。 locksカテゴリのさまざまなイベントをキャプチャするSQLプロファイラトレースを設定し、SSMS接続のspidをフィルタリングして両方のバージョンを試して、簡単に確認できます。

nolockは非常に危険な設定ですが、それを使用する際の潜在的な欠点(ダーティーリード、データの2回読み込み、またはまったく読まないこと)をすべて認識していますか?

+2

+1プロファイラでロックを監視できるかどうかわかりませんでした。 – Andomar

+0

はい私は認識しています。ありがとう –

1

最も内側のnolockで十分です。外側の選択に対してそれを繰り返す必要はありません。

あなたはそれを終了せずに取引を開始することで、これをテストすることができます。

begin transaction 
; with YourCte (... 

その後、あなたはManagement Studioを使用してロックを表示することができます。彼らはトランザクションがタイムアウトするまでそこにいます。

+0

隔離レベルによって異なります。共有ロックは通常、データが読み込まれるとすぐに解放されます。 –

2

「外側」クエリのNOLOCKも、内側のクエリにも適用されます。 CTEは、ビューまたはインラインテーブルのような単なるマクロです。udf:それ以上のものはありません。だから、実際にTable Hints on MSDNから

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

を(NOLOCKヒントを無視して)、「備考」

の下ですべてのロックヒントはテーブルを含む、クエリプランによってアクセスされるすべてのテーブルとビューに伝播されてきましたビュー内で参照されるビュー

この場合、必要なのは1つだけです。どこにいてもかまいません。

ここで問題となるのは、ジョインがある場所です。 cte1が2つのテーブルの結合であった場合は、各テーブルに必要です。または、より高いレベルまたは外側のレベルで1回指定します。

ああ、私は皆で参加します:NOLOCK is a bad idea

+0

ドキュメントを参照していただきありがとうございます。私はこれが受け入れられた答えであるべきだと思います! – chrnola

関連する問題