業務アプリケーションでは、データベースを更新する際にデータの整合性を保つ必要があります。そこで重要なのが、次の二つです。
トランザクション制御排他制御トランザクション制御
トランザクションとは、「ある意味をもった一連の処理のまとまり」のことで、完全に実行するか、またはまったく実行しないようにする必要がある原子性や、実行前後とも常にデータの整合性をを保持しなければならない一貫性という性質をもっております。
普通の意味では、アプリケーションの動作のうち、「ある意味を持った一連の処理のまとまり」のことをトランザクションといいます。そして、トランザクション制御とはこの一つのトランザクション内でデータの整合性が保たれるようにすることです。
SAP ERPでは、正式的な名称として、この「ある意味を持った一連の処理のまとまり」を「トランザクション」ではなく、「作業論理単位(Logical Unit of Work、略するとLUW)」と呼んでいます。関連がありますが、SAPの「トランザクション」は、トランザクションコードを使用して開始するアプリケーションプログラムのことと定義されています。
SAPでは、作業論理単位(LUW)はデータベース作業論理単位(DB LUW)とSAP作業論理単位(SAP LUW)と2種類が存在していますので、次にそれぞれ説明します。
DB LUW
データベース作業論理単位(DB LUW)
DB LUW は、データが常に整合性を持つようにするために、OracleやMSSQLなどのDBMS(データベース管理システム)が使用するメカニズムです。DBMS側では、一般的にこのDB LUWを「トランザクション」と呼んでいます。
SAPのDB LUWは、以下のように動作します。
DB LUWは一つのワークプロセスの中に完結しなければなりませんワークプロセスが正常又は異常終了する際に、コミットされていないDB更新に対して、暗黙的なデータベースコミット又はロールバックを行いますプログラムが汎用モジュール DB_COMMITを呼び出して明示的にデータベースコミットを行うことができます。プログラムがSAP LUWの命令(COMMIT WORK、ROLLBACK WORK)を呼び出してSAP LUWを終了する同時に、データベースLUWも終了します。開始されるときや、前のDB LUW がコミット又はロールバックで終了するときに、新しいDB LUWが開始されるDB LUW内で実行されるデータベース変更はデータベースロックを起こします、そのデータベースロックはLUWの終了に伴い、自動的に解放されます。SAP LUW
SAP作業論理単位(SAP LUW)
DB LUWはデータベースに対して分割できない連続したデータ上の操作であり、完全に終了するか、まったく実行しないかのいずれかにする必要があります。SAP LUWは、システムに対して分割できない業務処理であり、その業務処理全体を完了するか、あるいはまったく実行しないかのいずれかにする必要があります。SAP-LUW は通常、複数のダイアログステップや複数のDB LUW に及ぶことがあります。 同じSAP LUW で発生したDBデータ変更要求は、全て最後にデータベースに反映されることになります。
SAP LUWの終了
SAP LUWは、DB LUWのように暗黙的に終了することがありません。「COMMIT WORK」や「ROLLBACK WORK」命令を発行して、明示的に終了させる必要があります。
SAP LUWの原子性
一つのSAP LUWの中の各更新は複数のダイアログステップに跨って発行されることがよくありますが、発行時に即時に実行されるとすれば、別々のDB LUWのDBデータ操作になりますので、トランザクションとしての原子性が完全に崩れてしまうことになります。
SAPは、それらの更新を即時実行せずに、「更新依頼」オブジェクトを登録しておきます。「commit work」命令でSAP LUWがコミットされる際に、登録された「更新依頼」を一つのデータベースLUWで実行することにより、トランザクションとしての原子性を維持します。
但し、下記「エラー処理とデータの整合性」節で説明するように、各更新依頼の種類により完全な原子性が出来ない場合も存在します。
SAP LUWとDB LUW
SAPはワークプロセスごとに、固定データベース接続1 つが割り当てられています。そのデータベース接続でデータベースLUWが実行されますので、ワークプロセスは常に一つのDB LUWと結び付いております。
一方、SAP LUWは論理的な単位を提供しています、SAP LUWにおける各更新依頼は、結局、DB LUWによりデータの変更をデータベースに反映しないといけないですが、そのDB LUWは新たに生成されるものではなく、更新依頼が実行されるワークプロセスの固有のDB LUWとなります。そのDB LUWで発行された別の即時DB更新がもしあれば、同時にコミットされます、なお、エラーが発生する場合も、一緒にロールバックされることになります。
SAP LUWの単位
SAP LUW毎に、違う更新キーが割り当てられます、更新依頼はその更新キーと一緒に更新キューに登録されますので、それにより同じSAP LUWのものかどうかを判断できます。
アプリケーションプログラム( TYPE 1、TYPE M)はそれぞれ別のSAP LUWをもっています。但し、トランザクション( 機能)ではなく、「ダイアログモジュール」として起動される場合は、呼び出し元のアプリケーションプログラムのSAP LUWで実行されることになります。
更新依頼の種類と同期化制御
あとから実行するように登録される更新依頼は、下記のように幾つかの種類が存在します。種類によって、処理が実行されるワークプロセスと同期・非同期の制御などが変ります。
(1)サブルーチン更新依頼
PERMFORM <サブルーチン名>命令でON COMMITオプションを付けておければ、そのサブルーチンは即時に実行されることがありません、代わりに更新依頼として登録されます。
そのサブルーチン処理は、SAP LUWがcommit work命令でコミットされる際に、COMMIT WORK 命令と同じデータベース LUW の中で、同じワークプロセスによってインラインで実行されます。
同じワークプロセスなので、COMMIT WORK命令はすべてのサブルーチン更新依頼が処理完了するまでブロックされ、つまり同期化になります。
(2)汎用モジュール更新依頼
CALL <汎用モジュール>命令でIN UPDATE TASKオプションを付けておければ、その汎用モジュールは即時に実行されることがありません、その代わりに更新依頼として、汎用モジュール名とそのインタフェースパラメータがVBLOG という名称の特別なデータベーステーブルに格納されます。
その汎用モジュール処理は、SAP LUWがcommit work命令でコミットされる際に、更新プログラムにより実行されます。
デフォルトは、更新プログラムはcommit work命令が発行されたワークプロセスと別に、更新プロセスと呼ばれているバックグラウンドワークプロセスで非同期に処理を実行します。よってcommit work命令は待たずに、すぐ次の処理に入ることになります。
なお、下記のような場合、汎用モジュール更新依頼の実行はcommit work命令と同期になります。
①commit work命令にand waitオプションを付ける 更新プロセスで実行されるままですが、commit work命令は、全ての汎用モジュール更新依頼が処理完了するまでブロックされますので、同期になります。
②SET UPDATE TASK LOCAL
SET UPDATE TASK LOCALでローカル更新スイッチをONに指定された場合、更新プログラムは更新プロセスではなく、perfom … on commitのように、commit workと同じワークプロセスで実行されることになります。
更新用の汎用モジュールはU1(優先順位が高い)とU2(優先順位が低い)との2種類に分けられ、作成時に属性として指定することができます。更新プロセスで実行される時も別々のワークプロセスで実行されることになります。
(3) バックグラウンド更新依頼
CALL <汎用モジュール>命令でIN BACKGROUND TASKオプションを付けておければ、その汎用モジュールは即時に実行されることがありません、その代わりに更新依頼として登録されます。
その汎用モジュール処理は、SAP LUWがcommit work命令でコミットされる際に、commit work命令が発行されたワークプロセスと別に、バックグラウンドプロセスと呼ばれているワークプロセスで非同期に処理を実行されます。
下記のイメージ図で示されるように、同じSAP LUWの各更新依頼は、(1)→(2)のU1→(2)のU2→(3)の前後順で処理されます。
更新マネージャ「トランザクションコード:SM13」を使えば、更新依頼の処理状況を照会したり、エラーで中止された更新を再実行させたりすることができます。
エラー処理とデータの整合性
SAP LUWにおける各更新は、実行時エラーによっていずれかが失敗した場合、更新システムは下記のように処理します。
(1)FORM ルーチン内( PERFORM ON COMMIT で呼び出し)
-現在の更新トランザクションですでに実行された更新はロールバックされます。
-他の FORM ルーチンは開始されません。
-更新タスクまたはバックグラウンドタスク機能が開始されることはありません。
-エラーメッセージが画面に表示されます。
(2)V1 更新タスク汎用モジュール内( IN UPDATE TASK を依頼)
- V1 機能ですでに実行された更新はロールバックされます。
-更新タスクの依頼 (V1 または V2) はすべて取り消されます。
-バックグラウンドタスク依頼もすべて取り消されます。
- PERFORM ON COMMIT によって呼び出された サブルーチンですでに実行された更新は、ロールバック されません。
-エラーメッセージを送るようにシステム設定されている場合は、エラーメッセージが画面に表示されます。
(3)V2 更新タスク汎用モジュール内( IN UPDATE TASK を依頼)
-現在の V2 機能ですでに実行された更新はロールバックされません。
-まだ実行しなければならない更新タスク依頼 (V2) はすべて実行します。
-まだ実行しなければならないバックグラウンドタスク依頼はすべて実行します。
-V1 または V2 機能ですでに実行された更新はロールバックされません。
-サブルーチン( ON COMMIT で呼び出し)ですでに実行された更新はロールバックされません。
-エラーメッセージを送るようにシステム設定されている場合は、エラーメッセージが画面に表示されます。
(4)バックグラウンドタスク汎用モジュール内( IN BACKGROUND TASK DESTINATION を依頼)
-同一の DESTINATION のバックグラウンドタスク依頼はすべて取り消しされます 。
-すでに実行された他の更新はロールバックされません。
-エラーメッセージは画面に表示されません。