カーソルの同時実行 (データベース エンジン)

Microsoft SQL Server では、サーバー カーソルで次の 4 つの同時実行オプションがサポートされます。

  • READ_ONLY

  • OPTIMISTIC WITH VALUES

  • OPTIMISTIC WITH ROW VERSIONING

  • SCROLL LOCKS

  • READ_ONLY
    カーソルを使って位置指定更新することはできません。また、結果セットを構成する行にはロックが設定されません。

  • OPTIMISTIC WITH VALUES
    オプティミスティック同時実行制御はトランザクション制御理論の標準となる部分です。オプティミスティック同時実行制御は、カーソルが開いてから行を更新するまでの間に、他のユーザーやプロセスが行を更新する可能性がほとんどない状況で使用されます。このオプションでカーソルを開くと、基になる行にはロックが設定されないので、スループットを最大にするのに役立ちます。ユーザーが行を変更する場合、その行の現在の値と、その行を最後にフェッチしたときに取得された値が比較されます。変更されている値があった場合、サーバーは、他のユーザーまたはプロセスが既にその行を更新したと認識してエラーを返します。比較の結果、値が同じであれば、サーバーは変更を実行します。

    この同時実行オプションを選択すると、他のユーザーにより行が更新されたことを示すエラーが偶然に発生した場合、ユーザーまたはプログラマが、このエラーに対処しなければなりません。このエラーを受け取ったアプリケーションは、通常、カーソルを更新し、新しい値を取得し、新しい値に対して変更を行うかどうかをユーザーが判断できるようにします。SQL Server 6.5 以前では、text、ntext、および image 列は同時実行の比較に使用されませんでした。

  • OPTIMISTIC WITH ROW VERSIONING
    このオプティミスティック同時実行制御オプションは、行のバージョン管理に基づいています。行のバージョン管理では、基になるテーブルに、なんらかの種類のバージョン識別子が含まれている必要があります。サーバーはその識別子を使用することにより、カーソルに行を読み取った後にその行が変更されたかどうかを判断できます。SQL Server では、データベース内で行われた変更の相対順序を示す 2 進数である timestamp データ型によってこの機能が提供されます。それぞれのデータベースは、グローバルな現在のタイムスタンプ値 **@@**DBTS を持っています。timestamp 列を持つ行がなんらかの方法で変更されるたびに、SQL Server は現在の **@@DBTS の値を timestamp 列に格納してから、@@**DBTS を増分します。テーブルに timestamp 列がある場合、タイムスタンプは行レベルに下げられます。そのときにサーバーは行の現在のタイムスタンプ値と、最後にその行をフェッチしたときに格納されたタイムスタンプ値とを比較して、その行が更新されたかどうかを判断できます。サーバーはすべての列の値を比較する必要はなく、timestamp 列だけを比較します。アプリケーションが、timestamp 列のないテーブルに対して、行バージョン管理を伴うオプティミスティック同時実行を要求した場合、カーソルは、既定では、値に基づいたオプティミスティック同時実行制御を行います。

    注意

    リモート データ ソース上で開かれているカーソルの場合は、リモート ソースに timestamp 列がないと、カーソルによる更新は行えません。

  • SCROLL LOCKS
    このオプションは、ペシミスティック同時実行制御を実装します。ペシミスティック同時実行制御では、基になるデータベース行がカーソルの結果セットに読み取られる時点で、アプリケーションがそれらの行にロックを設定します。サーバー カーソルを使用する場合、行がカーソルに読み取られる時点でその行に更新ロックが設定されます。カーソルがトランザクションの内部で開かれた場合、トランザクション更新ロックが、そのトランザクションがコミットまたはロールバックされるまで保持されます。カーソル ロックが解除されるのは、次の行をフェッチする時点です。カーソルがトランザクションの外部で開かれた場合、次の行をフェッチする時点でそのロックが解除されます。したがって、完全なペシミスティック同時実行制御が必要な場合には、カーソルをトランザクションの内部で開く必要があります。更新ロックは、他のタスクが更新ロックまたは排他ロックを取得するのを防止し、それによって他のタスクがその行を更新するのを防ぎます。ただし、更新ロックは共有ロックを妨げないので、他のタスクも更新ロックを伴う読み取りを要求していない限り、他のタスクがその行を読み取ることは防止できません。

スクロール ロック

これらのカーソル同時実行オプションは、カーソル定義の SELECT ステートメントに指定されたロック ヒントによっては、スクロール ロックを発生させることがあります。スクロール ロックは、行をフェッチするとき各行に対して取得され、次にその行をフェッチするか、またはカーソルを閉じるまで保持されます。次に行のフェッチを実行するとき、サーバーは、新しくフェッチする行に対するスクロール ロックを取得し、前回フェッチした行に対するスクロール ロックを解放します。スクロール ロックはトランザクション ロックから独立しており、コミットまたはロールバック操作が行われている間も保持できます。コミットの実行時にカーソルを閉じるオプションを無効にした場合、COMMIT を実行しても開かれているカーソルは閉じられず、コミットの実行中もスクロール ロックが保持されるので、フェッチされたデータの分離が維持されます。

取得されるスクロール ロックの種類は、カーソル同時実行オプションおよびカーソルの SELECT ステートメントに指定されたロック ヒントによって決まります。

注意

スクロール ロックは、キーセット ドリブン カーソルと動的カーソルでのみサポートされます。

ロック ヒント

読み取り専用

値に基づくオプティミスティック

行のバージョン管理に基づくオプティミスティック

ロック

ヒントなし

-

-

-

更新

NOLOCK

-

-

-

-

HOLDLOCK

-

-

-

更新

UPDLOCK

-

-

-

更新

TABLOCKX

-

-

-

更新

他のすべて

-

-

-

更新

*NOLOCK ヒントを指定すると、そのヒントが指定されたテーブルがカーソルにより読み取り専用に設定されます。

カーソル同時実行オプションの指定

同時実行オプションはそれぞれのカーソル環境ごとに異なった方法で指定されます。

  • Transact-SQL カーソル

    DECLARE CURSOR ステートメントで READ_ONLY、SCROLL_LOCK、および OPTIMISTIC キーワードを指定します。OPTIMISTIC キーワードにより、行のバージョン管理に基づくオプティミスティック同時実行が指定されますが、Transact-SQL カーソルは値に基づくオプティミスティック同時実行オプションをサポートしていません。

  • ADO アプリケーション

    adLockReadOnlyadLockPessimisticadLockOptimistic、または adLockBatchOptimisticRecordset オブジェクトの LockType プロパティに指定します。

  • ODBC アプリケーション

    ステートメント属性 SQL_ATTR_CONCURRENCY を SQL_CONCUR_READ_ONLY、SQL_CONCUR_ROWVER、SQL_CONCUR_VALUES、または SQL_CONCUR_LOCK に設定します。