カーソルのロック
MicrosoftSQL 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 AdventureWorks.Sales.Store;
GO
/* Example 2 */
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO
BEGIN TRANSACTION
GO
DECLARE abc CURSOR STATIC FOR
SELECT * FROM AdventureWorks.Sales.Store;
GO
OPEN abc
GO
トランザクション分離レベルを "反復可能読み取り" に設定すると、例 1 の独立した SELECT ステートメントと、例 2 の DECLARE CURSOR に含まれる SELECT ステートメントはどちらも、行を読み取るごとに共有ロックを発生し、その共有ロックはトランザクションがコミットまたはロールバックされるまで保持されます。
ロックの取得
カーソルは独立した SELECT ステートメントと同じ規則に従いますが、取得したトランザクション ロックの種類については、ロックが取得された時点が異なります。独立した SELECT またはカーソルによって発生するロックは、必ず行の取得時に獲得されます。独立した SELECT の場合、ステートメントの実行時にすべての行が取得されます。しかし、カーソルの場合は、カーソルの種類によって、行が取得される時点が次のように異なります。
静的カーソルでは、カーソルを開くときに結果セット全体が取得されます。これにより、カーソルを開くときに結果セットの各行がロックされます。
キーセット ドリブン カーソルでは、カーソルを開くときに結果セットの各行のキーが取得されます。これにより、カーソルを開くときに結果セットの各行がロックされます。
通常の順方向専用カーソルを含む動的カーソルでは、行がフェッチされるまでは、その行が取得されません。このため、行がフェッチされるまで、その行に対するロックは取得されません。
高速順方向専用カーソルは、クエリ オプティマイザが選択した実行プランによって、いつロックを取得するかが変わります。動的プランが選択されると、行がフェッチされるまでロックは取得されません。作業テーブルが生成される場合は、作業テーブルに行が読み取られ、作業テーブルを開くとロックされます。
カーソルは、それぞれのカーソルに独自の同時実行指定もサポートしています。その中には、行がフェッチされるごとに、その行に対する追加ロックを発生させるものがあります。これらのスクロール ロックでは、その次のフェッチ操作が行われるか、またはカーソルが閉じられるまでロックが保持されます。コミットするときにカーソルを開いたままにする接続オプションを有効にすると、これらのロックは、コミットまたはロールバックの操作が実行されている間は保持されます。