4.2.7 テーブル排他なしTAMテーブルアクセス機能
TP1/FS/Table Access 05-00以前では,レコードを追加または削除する場合,テーブル単位の排他を確保します。これをテーブル排他ありTAMテーブルアクセス機能といいます。テーブル単位の排他については,「4.2.6 TAMテーブルの排他制御」を参照してください。
TP1/FS/Table Access 05-01以降では,テーブル単位の排他を確保しないで,レコード単位の排他資源だけを確保して,TAMテーブルのレコードにアクセスできます。これをテーブル排他なしTAMテーブルアクセス機能といいます。
(1) テーブル排他なしTAMテーブルアクセス機能の使用方法
テーブル排他なしTAMテーブルアクセス機能を使用するときは,TAMテーブルのアクセス形態に,「テーブル排他を確保しない,追加・削除できる更新型」を指定します。アクセス形態は,TAMサービス定義のtamtableコマンド定義句またはtamaddコマンドで指定してください。tamtableコマンド定義句については,マニュアル「OpenTP1 システム定義」を,tamaddコマンドについてはマニュアル「OpenTP1 運用と操作」を参照してください。
同じOpenTP1システムで,テーブル排他なしTAMテーブルアクセス機能を使用するTAMテーブルと,テーブル排他ありTAMテーブルアクセス機能を使用するTAMテーブルを混在できます。
テーブル排他なしTAMテーブルアクセス機能を使用するときに,既存のTAMファイルをtamcreコマンドによって再作成する必要はありません。
(2) 排他制御
(a) 排他の確保と解放
dc_tam_open関数およびレコードにアクセスする関数(dc_tam_read,dc_tam_write,dc_tam_delete)で排他をします。COBOL言語のUAPの場合は,レコードへアクセスするプログラムで排他をします。
確保された排他は,TAMテーブルにアクセスしたトランザクションが終了したときに解放されます。
(b) テーブル排他なしTAMテーブルアクセス機能でのTAMサービスの関数の排他指定と実際に排他される状態
テーブル排他なしTAMテーブルアクセス機能でのTAMサービスの関数の排他指定と実際に排他される状態を次の表に示します。
TAMサービスの関数とフラグに指定した値 |
テーブル排他 |
レコード排他 |
||
---|---|---|---|---|
dc_tam_open関数 |
テーブル排他 |
更新排他※1 |
− |
|
レコード排他 |
− |
− |
||
dc_tam_read関数 |
参照目的 |
排他なし |
− |
− |
排他あり |
− |
参照排他 |
||
更新目的 |
− |
更新排他 |
||
dc_tam_rewrite関数 |
− |
更新排他※2 |
||
dc_tam_write関数 |
− |
更新排他 |
||
dc_tam_delete関数 |
− |
更新排他 |
(c) 排他の確保処理
テーブル排他ありTAMテーブルアクセス機能と,テーブル排他なしTAMテーブルアクセス機能の,レコード更新時の排他確保処理を次の図に示します。
-
テーブル排他ありTAMテーブルアクセス機能では,dc_tam_writeで,この図の(1)(2)(3)に示すように参照目的のテーブル排他を確保し,更新目的のレコード排他を確保して,レコードを更新します。
-
テーブル排他なしTAMテーブルアクセス機能では,dc_tam_writeで,この図の(4)(5)に示すように更新目的のレコード排他を確保して,レコードを更新します。
テーブル排他ありTAMテーブルアクセス機能とテーブル排他なしTAMテーブルアクセス機能のレコード追加時の排他確保処理を次の図に示します。
-
テーブル排他ありTAMテーブルアクセス機能では,dc_tam_writeで,この図の(1)(2)に示すように更新目的のテーブル排他を確保して,レコードを追加します。
-
テーブル排他なしTAMテーブルアクセス機能では,dc_tam_writeで,この図の(3)(4)に示すように,更新目的のレコード排他を確保して,レコードを追加します。
このように,テーブル排他なしTAMテーブルアクセス機能とテーブル排他ありTAMテーブルアクセス機能では排他の確保処理が異なるため,トランザクション間でTAMテーブルへのアクセスが競合した場合の動作も異なります。テーブル排他ありTAMテーブルアクセス機能では,レコードを追加または削除するトランザクションが存在すると,ほかのトランザクションからは同じTAMテーブルに対してレコードを参照(排他あり),更新,追加,および削除できません。テーブル排他なしTAMテーブルアクセス機能では,アクセスするレコードが競合しなければ,同じTAMテーブルにアクセスできます。
テーブル排他ありTAMテーブルアクセス機能で,レコードアクセスが競合した場合の処理を次の図に示します。
-
UAP1がレコード1を追加するとします。UAP1では,この図の(1)(2)に示すように,更新目的のテーブル排他を確保して,レコードを追加します。
-
UAP2では,この図の(3)に示すように,参照目的のテーブル排他を確保できないため,レコード3を更新できません。
-
UAP3では,この図の(4)に示すように,更新目的のテーブル排他を確保できないため,レコード5を追加できません。
-
このため,UAP2およびUAP3は,UAP1のトランザクションが決着して排他が解放されるまで待つか,またはDCTAMER_LOCKで異常終了します。
テーブル排他なしTAMテーブルアクセス機能で,レコードアクセスが競合した場合の処理を次の図に示します。
-
UAP1がレコード1を追加するとします。UAP1では,この図の(1)(2)に示すように,レコード1に対して更新目的のレコード排他を確保して,レコードを追加します。
-
UAP2では,この図の(3)に示すように,レコード3に対して更新目的のレコード排他を確保して,レコード3を更新します。
-
UAP3では,この図の(4)に示すように,レコード5に対して更新目的のレコード排他を確保して,レコード5を追加します。
-
以上のように,テーブル排他を確保しないため,UAP1のトランザクションが決着していない状態でも,UAP2およびUAP3は同じTAMテーブルにアクセスできます。
(3) 注意事項
テーブル排他なしTAMテーブルアクセス機能を使用する場合,次の点に注意してください。
(a) dc_tam_open関数のテーブル排他
dc_tam_open関数をテーブル排他指定(flagsにDCTAM_TBL_EXCLUSIVEを指定)で発行した場合,dc_tam_open関数内でテーブル排他を確保しますが,レコードにアクセスする関数(dc_tam_read,dc_tam_write,dc_tam_delete)との排他制御はしません。つまり,テーブル排他指定のdc_tam_open関数同士はテーブル排他で待ち合わせをしますが,テーブル排他指定のdc_tam_open関数とレコードにアクセスする関数の間では排他の待ち合わせをしません。
dc_tam_open関数の排他方式を次の図に示します。
-
UAP1では,dc_tam_open関数をテーブル排他指定(flagsにDCTAM_TBL_EXCLUSIVEを指定)で発行し,この図の(1)に示す更新目的のテーブル排他を確保します。
-
UAP2では,テーブル排他指定でdc_tam_open関数を発行しますが,この図の(2)に示すように,更新目的のテーブル排他が確保できないため,UAP1のトランザクションが決着して排他が解放されるまで待つか,またはDCTAMER_LOCKで異常終了します。
-
UAP3では,レコード排他指定(flagsにDCTAM_REC_EXCLUSIVEを指定)でdc_tam_open関数を発行しているため,dc_tam_open関数は正常終了します。レコード3の更新では,この図の(3)に示すように,レコード3に対して更新目的のレコード排他を確保して,レコード3を更新します。
(b) レコード追加時の空きレコードの割り当て
レコードの削除をした場合,レコードを削除したトランザクションがコミットするまで,削除したレコードは空きレコードにはなりません。そのため,レコードを削除したトランザクションがコミットするまで,削除したレコードの領域は追加するレコードに割り当てられません。ただし,レコードを削除したトランザクションと同一トランザクション内で,キー値が同じレコードを追加する場合には,削除したレコードの領域が割り当てられます。
したがって,追加するレコード数分の空きレコードがない状態でレコードを追加する場合,追加するトランザクションと同じトランザクションで異なるキー値のレコードを削除しても,レコードの追加はDCTAMER_NOAREAでエラーリターンします。
レコードの追加がDCTAMER_NOAREAとなる例を次の図に示します。
-
最大レコード数が3のTAMテーブルにキー値1,キー値2,およびキー値3のレコードが格納されているとします。UAP1では,キー値1,キー値2,キー値3を削除し,キー値4を追加します。
-
キー値1の削除では,この図の(1)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値2の削除では,この図の(2)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値3の削除では,この図の(3)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値4の追加では,この図の(4)に示すように,空きレコードがないため,DCTAMER_NOAREAでエラーリターンします。
レコードの追加がDCTAMER_NOAREAとならないようにするには,追加するレコード数分の空きレコードを用意するか,またはレコードを削除したトランザクションをコミットしたあとでレコードを追加する必要があります。
追加するレコード数分の空きレコードを用意する場合の処理を次の図に示します。
-
TAMテーブルの最大レコード数を4に増やします。TAMテーブルには,キー値1,キー値2,およびキー値3のレコードが格納されているとします。UAP1では,キー値1,キー値2,キー値3を削除し,キー値4を追加します。
-
キー値1の削除では,この図の(1)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値2の削除では,この図の(2)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値3の削除では,この図の(3)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値4の追加では,この図の(4)に示すように,空きレコードであるレコード4に追加できます。
レコードを削除したトランザクションをコミットしたあとでレコードを追加する場合の処理を次の図に示します。
-
最大レコード数が3のTAMテーブルにキー値1,キー値2,およびキー値3のレコードが格納されているとします。UAP1では,キー値1,キー値2,キー値3を削除したあとでいったんコミットし,次のトランザクションでキー値4を追加します。
-
キー値1の削除では,この図の(1)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値2の削除では,この図の(2)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
キー値3の削除では,この図の(3)に示すように,レコード1は削除中になりますが,空きレコードにはなりません。
-
コミットでは,この図の(4)に示すように,削除中のレコード1,レコード2,レコード3を空きレコードにします。
-
キー値4の追加では,この図の(5)に示すように,空きレコードであるレコード1に追加できます。
(c) アクセス形態の変更
tamaddコマンドによって,テーブル排他ありTAMテーブルアクセス機能を使用するTAMテーブルから,テーブル排他なしTAMテーブルアクセス機能を使用するTAMテーブルに変更したり,テーブル排他なしTAMテーブルアクセス機能を使用するTAMテーブルから,テーブル排他ありTAMテーブルアクセス機能を使用するTAMテーブルに変更したりすることはできません。変更した場合,tamaddコマンドは異常終了します。
テーブル排他ありTAMテーブルアクセス機能を使用するか,テーブル排他なしTAMテーブルアクセス機能を使用するかを変更する場合は,TAMサービス定義のtamtableコマンド定義句を変更してOpenTP1システムを正常開始するか,TAMサービス定義に登録しないでOpenTP1システムを正常開始してtamaddコマンドで新規登録して変更してください。
(d) デッドロック
テーブル排他ありTAMテーブルアクセス機能を使用していたTAMテーブルを,テーブル排他なしTAMテーブルアクセス機能を使用するように変更する場合,デッドロックとなることがあります。詳細は,「4.2.11(1)(b) テーブル排他なしTAMテーブルアクセス機能を使用している場合」を参照してください。
(4) プログラムインタフェース
dc_tam_status関数およびCBLDCTAM('INFO ')以外は,テーブル排他ありTAMテーブルアクセス機能と同じプログラムインタフェースを使用してTAMテーブルにアクセスできます。
なお,UAPは,リコンパイルまたは再リンケージが必要となることがあります。リコンパイルが必要な条件を表4-11に,再リンケージが必要な条件を表4-12に示します。
条件 |
必要な作業 |
|||
---|---|---|---|---|
dc_tam_status使用 |
あり |
st_acs_type参照 |
あり |
アクセス形態の情報として,新定数DCTAM_STS_RECLCKが返却されるので,UAPを修正し,リコンパイルし直す必要があります。 |
なし |
リコンパイルは不要です。 |
|||
なし |
条件 |
必要な作業 |
|
---|---|---|
AP使用ライブラリ |
アーカイブライブラリ |
再リンケージが必要です。 |
共用ライブラリ |
再リンケージは不要です。 |
dc_tam_status関数では,DC_TAMSTAT構造体のst_acs_typeにアクセス形態を返却します。このst_acs_typeに返却する値にDCTAM_STS_RECLCKを追加します。DCTAM_STS_RECLCKは,「テーブル排他を確保しない,追加・削除できる更新型」というアクセス形態を表し,テーブル排他なしTAMテーブルアクセス機能を使用するTAMテーブルであることを意味します。
dc_tam_status関数のそのほかの返却値および使用方法については,マニュアル「OpenTP1 プログラム作成リファレンス C言語編」を参照してください。
CBLDCTAM('INFO ')では,データ名Kにアクセス形態を返却します。このデータ名Kに返却する値にVALUE 'L'を追加します。VALUE 'L'は,「テーブル排他を確保しない,追加・削除できる更新型」というアクセス形態を表し,テーブル排他なしTAMテーブルアクセス機能を使用するTAMテーブルであることを意味します。CBLDCTAM('INFO ')のそのほかの返却値および使用方法については,マニュアル「OpenTP1 プログラム作成リファレンス COBOL言語編」を参照してください。
(5) 定義インタフェース
TAMサービス定義のtamtableコマンド定義句では,-aオプションにアクセス形態を指定します。テーブル排他なしTAMテーブルアクセス機能を使用する場合,この-aオプションのオプション引数にreclckを指定してください。reclckは,「テーブル排他を確保しない,追加・削除できる更新型」というアクセス形態を表し,テーブル排他なしTAMテーブルアクセス機能を使用するTAMテーブルであることを意味します。
tamtableコマンド定義句のそのほかのオプションおよび使用方法については,マニュアル「OpenTP1 システム定義」を参照してください。