カーソルのロック

SQL Server では、カーソル定義の SELECT ステートメントでも、それ以外の SELECT ステートメントに適用されるトランザクション ロックの規則が適用されます。ただし、カーソルの場合、カーソル同時実行レベルの指定に基づき、スクロール ロックのセットを追加で取得できます。

カーソル定義の SELECT ステートメントも含めて、SELECT ステートメントで取得されるトランザクション ロックは、次の項目によって制御されます。

  • その接続のトランザクション分離レベルの設定

  • FROM 句に指定されたロック ヒント

これらのロックは、カーソルの SELECT ステートメントと独立した SELECT ステートメントのどちらの場合も、対応する現在のトランザクションが終了するまで保持されます。SQL Server を自動コミット モードで実行しているとき、個々の SQL ステートメントがトランザクションになり、ステートメントの終了時にロックが解放されます。SQL Server が明示的または暗黙的なトランザクション モードで動作されているときは、トランザクションがコミットまたはロールバックされるまでロックが保持されます。

たとえば、次の 2 つの Transact-SQL の例で行われるロックは、本質的には同じものです。

/* Example 1 */
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO
BEGIN TRANSACTION
GO
SELECT * FROM AdventureWorks2008R2.Sales.Store;
GO

/* Example 2 */
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO
BEGIN TRANSACTION
GO
DECLARE abc CURSOR STATIC FOR
SELECT * FROM AdventureWorks2008R2.Sales.Store;
GO
OPEN abc
GO

トランザクション分離レベルを "反復可能読み取り" に設定すると、例 1 の独立した SELECT ステートメントと、例 2 の DECLARE CURSOR に含まれる SELECT ステートメントはどちらも、行を読み取るごとに共有ロックを発生し、その共有ロックはトランザクションがコミットまたはロールバックされるまで保持されます。

ロックの取得

カーソルは独立した SELECT ステートメントと同じ規則に従いますが、取得したトランザクション ロックの種類については、ロックが取得された時点が異なります。独立した SELECT またはカーソルによって発生するロックは、必ず行の取得時に獲得されます。独立した SELECT の場合、ステートメントの実行時にすべての行が取得されます。しかし、カーソルの場合は、カーソルの種類によって、行が取得される時点が次のように異なります。

  • 静的カーソルでは、カーソルを開くときに結果セット全体が取得されます。これにより、カーソルを開くときに結果セットの各行がロックされます。

  • キーセット ドリブン カーソルでは、カーソルを開くときに結果セットの各行のキーが取得されます。これにより、カーソルを開くときに結果セットの各行がロックされます。

  • 通常の順方向専用カーソルを含む動的カーソルでは、行がフェッチされるまでは、その行が取得されません。このため、行がフェッチされるまで、その行に対するロックは取得されません。

  • 高速順方向専用カーソルは、クエリ オプティマイザーが選択した実行プランによって、いつロックを取得するかが変わります。動的プランが選択されると、行がフェッチされるまでロックは取得されません。作業テーブルが生成される場合は、作業テーブルに行が読み取られ、作業テーブルを開くとロックされます。

カーソルは、それぞれのカーソルに独自の同時実行指定もサポートしています。その中には、行がフェッチされるごとに、その行に対する追加ロックを発生させるものがあります。これらのスクロール ロックでは、その次のフェッチ操作が行われるか、またはカーソルが閉じられるまでロックが保持されます。コミットするときにカーソルを開いたままにする接続オプションを有効にすると、これらのロックは、コミットまたはロールバックの操作が実行されている間は保持されます。