単純な選択クエリはロックを取得しますか?


13

私はSQL Serverを初めて使用します。次の非常に単純なselectステートメントがロックを取得するかどうかを理解したいと思います。

Select * from Student;

ステートメントがbegin tranブロック内で実行されない場合を考慮してください。


1
これは、あなたが考えているよりもはるかに複雑な質問です。答えは多くのことに依存します(セッショントランザクション分離レベルは何ですか?読み取りコミットスナップショット分離はオンになっていますか?スキャンされたインデックスには、行またはページのロックを防止するオプションが設定されていますか?)行はテーブルにありますか?テーブルはパーティション分割されていますか?)。ここで読み始めるには良い点です。
ジョンセイゲル

回答:


5

はい、デフォルトで読み取る行で共有ロックを取得します(読み取りを行うクラスター化インデックスのすべてのページでIntent Sharedロックも取得します)。これは、ダーティー読み取りを防ぐために行われます。ただし、これをバイパスする方法があります(SQL Serverにはnolockヒントがあります)。ステートメントがBEGIN TRANにない場合は、SELECTステートメントの実行後にロックが解除されます。

詳細はこちらをご覧ください:

http://msdn.microsoft.com/en-us/library/ms184286(v=sql.105).aspx http://www.sqlteam.com/article/introduction-to-locking-in-sql-server


また、トランザクション分離レベルを設定して、コミットされていない状態を読み取ることもできます。
ゼーン

1
SELECTが10行を読み取る場合、10行すべてが読み取られるまで、または行ごとに取得および解放されるまで、10個の共有ロックが保持されますか?
イアンウォーバートン

25

次の非常に単純な選択ステートメントがロックを取得するかどうかを理解したいと思います

既定のトランザクション分離レベルで実行されているクエリは、ダーティリードを防ぐために常に共有ロックを取得するという一般的な誤解SELECTです。READ COMMITTED

SQL Serverは、コミットされていないデータを読み取らずにそれらのデータを読み取る危険性がない場合に、共有行レベルロックの取得を回避できます(ただし、より高いレベルのIntent-Shared(IS)ロックは引き続き取得されます)。

共有行ロック取得された場合(おそらく、別の同時トランザクションが行が存在するページを変更したため)、それらはSELECTステートメントが完了するずっと前に解放できます。

ほとんどの場合、サーバーが次の行を処理する直前に行は「ロック解除」されます。デフォルトの分離レベルで取得された共有ロックが、トランザクションの最後ではなく、現在のステートメントの最後まで保持される状況があります。

NOLOCKテーブルヒントで現在の分離レベルを上書きすることはほとんど悪い考えです。

ロックは実装の詳細です。SQL Serverは、必要に応じてロックを取得し、現在の分離レベルで提供されるセマンティック保証を確実に満たします。確かに、ロックが取得される理由について少し知っておくと便利な場合もありますが、ロックを予測しようとすると逆効果になることがよくあります。

SQL Serverは、さまざまな分離レベルを提供します。データ消費者が必要とする保証と動作を提供するものを選択してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.