接続のコンテキストにおけるカーソルの動作

他のステートメント・ハンドルとの書き込み競合時における一般的な読み取りカーソル

アプリケーションには同時に同じ表に読み取りと書き込みの両操作を行うステートメント・ハンドルが複数存在する可能性があります。競合が発生するのは、あるハンドルが表に読み取りか書き込みの操作を行っている最中に、別のハンドルがその表に書き込み操作 (例えば、UPDATEとか DELETE とか INSERT) を行おうとするときです。 DB2 Everyplace の動作では、読み取りカーソルが継続的に作動し、いつも最新の現行データを読み取ります。索引を使用しているかどうかに関係なく、書き込みが競合しても、読み取りが継続されます。例えば、あるアプリケーションに 2 つのステートメント・ハンドルが存在するとします。ハンドル #1 は表 T から行を取り出すのに使用され、 ハンドル #2 は同じ表から行をいくつか削除するのに使用されます。それぞれのハンドルは異なるスレッド (例えば、Java スレッド環境) で作成された可能性があります。

この場合、考えられるシナリオは次のとおりです。

// Fetch 2 rows from table T
   Statement handle 1: execute "SELECT A FROM T WHERE primary_key < 10"
   Statement handle 1: fetch one row; fetch another row
    // Delete some rows in table T
   Statement handle 2: prepare "DELETE FROM T WHERE primary_key = ?"
   Statement handle 2: execute
    // Continue to fetch one more row from T
   Statement handle 1: fetch one row

実行のこの時点において、ステートメント・ハンドル #1 は索引を使用しているかどうかにかかわらず、次の行 (次の行が存在する場合) のフェッチを継続することができます。上記のシナリオでは、主キーが存在することから、索引が使用されています。重要な点は、DB2 Everyplace はハンドル #1 のカーソル位置を、先に進める前にカーソルの現在位置を使用して変更しようとするということです。現在位置がもはや存在しない場合 (例えば、該当する行が別のステートメント・ハンドルにより削除されてしまった場合) には、カーソルはフェッチが終了すると即座に次の位置に進みます。同様に、次の位置が別のステートメント・ハンドルにより削除された場合には、カーソルは発生した「穴」をスキップして次の位置まで進むことができます。

他のステートメント・ハンドルとの書き込み競合時における両方向スクロール・カーソル

前のセクションで取りあげた例と似通った例について考えてみます。読み取りカーソルが両方向スクロール・カーソルであるという点が前回と異なります。そのカーソルが「インセンシティブ (無反応)」な両方向スクロール・カーソルである場合は、問題にはなりません。結果セットが定義によって変化しないからです。カーソルが「インセンシティブ」でない場合は、 その動作は上述した通常の読み取りカーソルと一致します。競合後の読み取りカーソルの動作は、基本的に、結果セットは最新の現行表データに従って再計算され、現在行セットの開始点は維持されます。現在行が削除されていれば、カーソルは次の行に進みます。

次の例では、CLP を使用した両方向スクロール・カーソルの場合を示しています。表 T には、6 つの行があるものとします。

create table T (a int, b int) 
     create index idx1 on T(a) 
     insert into T values (1, 1) 
     insert into T values (2, 2) 
     insert into T values (3, 1) 
     insert into T values (3, 2) 
     insert into T values (3, 3) 
     insert into T values (4, 4) 

さらに、1 つは読み取り用でもう 1 つは削除用の 2 つのステートメント・ハンドルを有するアプリケーションの例を考えてみます。

Statement handle 1: enable scrollable cursor; 
Statement handle 1: execute "SELECT A FROM T WHERE a < 10"
Statement handle 2: prepare "DELETE FROM T WHERE a = ?" 
Statement handle 1: fetchscroll with SQL_FETCH_FIRST
-- get (1, 1) 
Statement handle 1: fetchscroll with SQL_FETCH_NEXT  
-- get (2, 2) 
Statement handle 1: fetchscroll with SQL_FETCH_NEXT  
-- get (3, 1) 
Statement handle 2: execute
--- suppose delete row (2, 2) 
Statement handle 1: fetchscroll with SQL_FETCH_NEXT  
-- re-compute previous rows, and return (3, 2) 
Statement handle 1: fetchscroll with SQL_FETCH_PRIOR
-- get (3, 1) 
Statement handle 1: fetchscroll with SQL_FETCH_PRIOR
-- get (1, 1)  note that (2, 2) is gone 
Statement handle 1: fetchscroll with SQL_FETCH_ABSOLUTE, offset 2
-- get (3, 1)  note that (2, 2) is gone 
Statement handle 1: fetchscroll with SQL_FETCH_ABSOLUTE, offset 5
-- get (4, 4)

自動コミット・モードを含めた、コミットとロールバックにおけるカーソル

トランザクション・モードか自動コミット・モードであるかにかかわりなく、オープン・カーソルは、コミットが行われている間はオープン状態のままです。オープン・カーソルはロールバックでクローズされます。

オブジェクトの従属関係

ステートメント・ハンドル H を介して SQL ステートメントを作成すると、特定のオブジェクトとの間に何らかの従属関係が生じることがあります。例えば、索引 Idx を介して表 T から行を選択するには、表 T と索引 Idx が存在しなくてはなりません。これらのオブジェクトが別のステートメント・ハンドルで削除された場合 (例えば、索引 Idx がドロップした場合)、H を使用して SQL ステートメントを再実行するには、そのステートメントの再コンパイルを強いられることになります。その結果、照会プランが以前と異なったり、エラーが戻されたりすることがあります。