並行性に関するプログラミング
アクセスされるデータの保全性を保護しつつ、他のプロセスによる同じデータへのアクセスが長時間にわたって妨げられることのないように、アプリケーション・プログラムを設計することができます。
このタスクについて
Db2が並行性を制御する基本的な方法は、作業単位にロックを使用することです。 ある作業単位が完了すると、その作業単位が暗黙的に獲得したロックはすべて解放されて、 新しい作業単位を開始できます。 プログラム内の作業単位によって使用される処理時間は、Db2が他のユーザーに対してそのロックされたデータにアクセスできなくする時間の長さに影響を与えます。 複数のプログラムが同じデータを並行して使おうとすると、各プログラムの作業単位に要する時間を極力短くして、プログラム間の干渉を最小限に抑える必要があります。
プロシージャー
並行性のためにアプリケーションを設計するためには。
- アプリケーションが同じ順序でデータにアクセスするようにプログラムします。2 つのアプリケーションが表の同じ行に同じ順序でアクセスする場合、1 つのアプリケーションはもう 1 つのアプリケーションを待機する必要が生じますが、デッドロックは発生しません。 そのため、異なるアプリケーションが同じ順序で行にアクセスし、同じ順序で表にアクセスするようにプログラムすることが推奨されています。
- コミットすることが現実的である場合は、できるだけ早く作業をコミットしてください。それにより、読み取り専用アプリケーションであっても、不要なロック競合が回避されます。
長時間走行でリカバリー単位 (UR) が長くなる場合に頻繁にコミット・ポイントを設定すると 、CPU 使用率およびログ書き込み入出力回数が増加する可能性はありますが、次のような利点があります。
- ロック競合の削減 (特にデータ共用環境の場合)
- ロック回避の効率の向上 (特にデータ共用環境の場合)
- システム障害後の Db2 システムの再起動にかかる時間を短縮
- アプリケーション障害発生後、またはアプリケーションによる明示的ロールバック要求後、 リカバリー単位をロールバックするための経過時間削減
- オンライン REORG などのユーティリティーが割り込む機会の増加
頻繁にコミットしないアプリケーションを特定するために、URCHKTH サブシステム・パラメーターまたは URLGWTH サブシステム・パラメーターの使用を検討してください。 URCHKTH は、UR がコミットを発行せずにあまりにも多くのチェックポイントが発生した場合にその状況を特定します。 これは、システム・アクティビティー全体をモニターするのに役立ちます。 URLGWTH は、コミット・ポイントからコミット・ポイントまでの間にあまりにも多くのログ・レコードを書き込んでいる可能性のあるアプリケーションを検出できます。このようなアプリケーションは、重要な表のリカバリーに時間がかかる状態を潜在的に作り出しています。
あるアプリケーションは通常操作の条件下では使用するシステムにおけるコミット頻度の基準に順応して いたとしても、システムのワークロードの変動に基づいてバリエーションが生じる可能性があります。 例えば、システム負荷が軽い状態では、優先順位の低いアプリケーションがコミットを頻繁に発行して いたとしても構わないでしょう。 しかし、システム負荷が重い状態では、このアプリケーションによる CPU 使用が優先された場合には、 その結果としてこのアプリケーションが URCHKTH サブシステム・パラメーターによって設定された規則に違反する 可能性があります。 この理由により、単に実行された SQL 処理の量を基にするのではなく、 最後のコミットからの経過時間を基にしてコミットを発行する論理をアプリケーションに 追加してください。 さらに、読み取り専用の実行時間の長い作業単位では コミット・ポイントを頻繁に設定するようにして、ロックによる競合を低減し、オンライン REORG などの ユーティリティーがデータにアクセスできる機会を提供してください。
頻繁にコミットすることが重要なのは、ログされていないオブジェクトでも、ログされているオブジェクトでも同じです。 例えば、作業が NOT LOGGED オプションを指定して定義された表スペース上で行われる場合も、必ず作業を頻繁にコミットしてください。 特定のトランザクションが、ログされていない表スペースにある表のみを変更する場合でも、リカバリー単位は更新の実行前に引き続き設定されます。 取り消し処理では、適用対象の取り消しログ・レコードを探して逆方向にログを読み続けます。このことは、このリカバリー単位がログに記録されているので、リカバリー単位の先頭を検出するまで続きます。 したがって、このようなトランザクションは頻繁にコミットして、取り消し処理がログを逆方向にたどって、リカバリー単位の先頭を見つけ出すまでの長さを限定する必要があります。
- アプリケーション・プログラムにロジックを組み込んで、デッドロックまたはタイムアウト後に競合状況からの回復を、援助を受けずに再試行します。このような方法では、運用担当者の援助を求めなくても 当該の状況からリカバリーできる可能性があります。 以下の方法で、タイムアウトとデッドロックのどちらが発生しているかを判別できます。
- SQLCA の SQLERRD(3) フィールド
- GET DIAGNOSTICS ステートメント
- ほとんどのアプリケーションをISOLATION(CS)およびCURRENTDATA(NO)オプションでバインドします。これらのオプションにより、 Db2 は早期にロックを解除し、多くの場合ロックをかけずに済むようになります。一般的には、ISOLATION(CS) を使用すると、Db2 は取得済みのロックをできるだけ早く解放できるようになります。 CURRENTDATA(NO) を指定すると、通常、 Db2 がロックを最も少なく取得できるようになり、 ロックの回避が改善されます。ISOLATION(CS) および CURRENTDATA(NO) を使用する場合は、SKIPUNCI サブシステム・パラメーターの値を YES にして使用し、コミットされていない挿入の結果を読み取りプログラムが待たないようにします。
- ISOLATION(CS) および CURRENTDATA(NO) を使用しない場合は、優先順位の低い順に、以下のバインド・オプションを使用します。
- ISOLATION(CS) および CURRENTDATA(YES)。これは、アプリケーションに戻されるデータが、 次の FETCH 操作までは変更されてはならない場合。
- ISOLATION(RS)。これは、アプリケーションに戻されるデータが、 アプリケーションがコミットまたはロールバックするまで変更されてはならない場合。 ただし、他のアプリケーション処理が追加行を挿入するかどうかには留意しません。
- ISOLATION(RR)。これは、照会の結果として評価されるデータが、 アプリケーションがコミットまたはロールバックするまで変更されてはならない場合。 この場合には、新規行を応答セットに挿入することはできません。
- ISOLATION(UR) は慎重に使用する。資源回収サービスの付属施設 URの分離は、行やページのロックをほとんど取得しない。 この 分離機能は高速で、競合はほとんど生じませんが、 コミットされていないデータを読み取ります。 アプリケーションおよびエンド・ユーザーが、 生じる可能性がある論理的な矛盾を受け入れることができない場合には、それを使用しないで ください。
アプリケーションで非コミット・データの読み取りよりも、データの除外を優先する場合は、代わりに SKIP LOCKED DATA 文節の使用を検討してください。
- シーケンス・オブジェクトを使用して固有シーケンス番号を生成する。固有シーケンス番号を生成する方法の 1 つに、ID 列を使用する方法があります。
ただし、ID 列は、1 つの 表のうちの 1 つの列としてその表に関連付けられ、結び付けられ、1 つの表には 1 つの ID 列しか持てません。 ご使用のアプリケーションは、多数の表を通した 1 つのシーケンスの固有番号、または各表ごとの 複数のシーケンスを使用する必要が生じる場合があります。 ユーザー定義オブジェクトであるシーケンスは、アプリケーションが Db2 に一意の数値キー値を生成させ、複数の行やテーブルにわたってキーを調整する方法を提供します。
シーケンスを使用するとロック競合問題を回避できます。このロック競合問題が 発生する可能性があるのは、アプリケーションがその独自のシーケンスをインプリメント時に、 各トランザクションが増分する必要のあるシーケンス番号の入った 1 行だけの表を作成した結果 です。 Db2 のシーケンスでは、多くのユーザーが待つことなく同時にアクセスし、シーケンスをインクリメントすることができます。 Db2 シーケンスをインクリメントしたトランザクションがコミットするのを待たずに、別のトランザクションがシーケンスを再びインクリメントすることを許可する。
- 作業単位が長くなる可能性がある複数行操作 (数行の挿入、位置付け更新、および位置付け削除など) の検査を行う。これは、ほかのユーザーがデータにアクセスする際の並行性に 影響する可能性があります。 ホスト変数配列のサイズを調整し、挿入、更新の間のコミット、 およびロック・エスカレーションの回避によって、競合を最小限に抑えることができます。
- グローバルトランザクションを使用すると、 Db2 やその他のトランザクションマネージャが単一のトランザクションに参加し、同じロックを共有したり、同じデータにアクセスしたりできるようになります。資源回収サービス付属施設(RRSAF)は、資源回収サービス(RRS)と呼ばれるコンポーネントに依存している。 z/OS® 資源回収サービス(RRS)と呼ばれるコンポーネントに依存している。 RRSは、製品間の二相コミット作業を調整するシステム全体のサービスを提供する。 z/OS 製品を提供します。 RRSの下で実行されるRRSAFアプリケーションと IMS トランザクションでは、 Db2 エージェントを1つのグローバルトランザクションにまとめることができます。
グローバルトランザクションでは、複数の Db2 エージェントが単一のグローバルトランザクションに参加し、同じロックを共有し、同じデータにアクセスすることができます。 グローバルトランザクション中の2つのエージェントが、作業単位内の同じ Db2 オブジェクトにアクセスした場合、それらのエージェントは互いにデッドロックやタイムアウトを起こすことはありません。 以下の制約事項が適用されます。
- Parallel Sysplex®はグローバルトランザクションには対応していません。
- グローバル・トランザクションの「分岐」のそれぞれがロックを共用するので、 トランザクションの 1 つの分岐で発行したコミットされていない更新は、 そのトランザクションの他の分岐からは認識できます。
- クレーム / ドレーンは、グローバル・トランザクションの分岐にまたがってはサポートされません。 これは、同じグローバル・トランザクションの別々の分岐 から CREATE、DROP、ALTER、GRANT、または REVOKE を発行しようとすると、 デッドロックまたはタイムアウトになる可能性があることを意味します。
- LOCK TABLE によって、 グローバル・トランザクションの分岐間でデッドロックまたはタイムアウトが発生する場合があります。
- オプティミスティック並行性制御を使用する。オプティミスティック並行性制御 は、並行データ・アクセスでのデータベース・ロッキングに対して、さらに高速でスケーラブルなロッキングを行う代替方法です。 これによって、特定のリソースを他のトランザクションが使用できなくなる時間が最小になります。
アプリケーションが、オプティミスティック並行性制御を使用する場合、 ロックは、読み取り操作の直前に取得され、即時に解放されます。 更新ロックは、更新操作の直前に取得され、 そのトランザクションの終了まで保持されます。 オプティミスティック並行性制御は、RID および行変更トークンを使用して、 最後の読み取り操作以降に、別のトランザクションによってデータが変更されたかどうかをテストします。
Db2 は行が変更された時刻を特定できるため、ロックが保持される時間を制限しながらデータの整合性を確保することができます。 楽観的同時実行制御では、 Db2 は読み取り操作の直後に行またはページのロックを解除します。 Db2 また、FETCHの実行ごとに行ロックを解除し、位置指定の更新または削除のみに対して新しいロックを取得することで、データの整合性を確保します。
オプティミスティック並行性制御をインプリメントするには、行変更タイム・スタンプ列を、CREATE TABLE ステートメントまたは ALTER TABLE ステートメントで設定する必要があります。 この列は、以下のいずれかの NULL 特性で定義する必要があります。
- NOT NULL GENERATED ALWAYS FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP
- NOT NULL GENERATED BY DEFAULT FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP
行変更タイムスタンプ列を確立した後、 Db2 は、この列の内容を維持します。 更新を行う時点での条件としてこの変更トークンを使用する場合、 WHERE 文節でこの列に適切な述部を指定できます。