ロックとトランザクション: 物理トランザクションと遅延トランザクション

dbMAGIC から Magic eDeveloper に名称が変更されてから(つまりV9以降)、タスク特性に「トランザクションモード」という設定が追加されました。
実は、この設定、非常に重要な意味を持っています。
知らずに開発していると、いずれ痛いことになります。

トランザクションモード選択肢は4つありますが、大きく分けると「物理」か「遅延」のどちらかです。
まずは、この両者の違いを理解しなければなりません。
また、この設定は、キャッシュにも影響を及ぼします。
物理トランザクションでは、タスク特性のキャッシュ範囲の設定を開発者が変更することができますが、遅延トランザクションでは「位置とデータ」に固定されます。
キャッシュについては、こちらで説明しています。

dbMAGIC 時代(つまりV8以前)にはトランザクションモードの設定はありません。
全て、物理トランザクションとして動作していました。
V9以降、ブラウザタスク(ブラウザクライアント)が新しいタスクタイプとして加わりましたが、これは必ず遅延トランザクションになります。
そして、オンラインタスクやバッチタスクでは、物理/遅延、どちらでも選択可能となりました。

V8から移行したプログラムは自動的に物理トランザクションとなるので、従来と同様の動作を重視するなら、新規作成するタスクも物理トランザクションにした方が良いでしょう。
しかし、ブラウザクライアントやV10のリッチクライアントでは、遅延トランザクションが使われるので、それに合わせて、オンラインタスクでも積極的に遅延トランザクションに取り組むという考えもあるかもしれません。
個人的には、従来型のC/Sプログラムでは物理トランザクションで統一して、Webアプリケーションのみ遅延にするというスタンスにしています。
(Webでもバッチタスクでは物理トランザクションが原則です。)

さて、物理トランザクションと遅延トランザクションの違いですが、遅延という表現から「何か」が遅れるのだという予想ができます。
物理トランザクションに対して、遅延トランザクションは、「DBMSへの書込系コマンドの送出が遅れる」と理解しましょう。

処理フローのところで説明していますが、Magicの処理の基本は、
  1レコード読込→1レコード処理(メモリ上)→1レコード書込
というレコードループです。
既存レコードに対して更新するときは、そのレコードにロックをかけることも必要ですが、物理トランザクションではロックが必要時にリアルタイムで実行されます。
また、SQL系DBMS(OracleやMS SQL Server)では、ロックの前にトランザクションを宣言することも必要です。
「書込系コマンド(そんな一般用語はありませんけど)」とは、
  DBMSへのトランザクションの宣言→ロック→更新
のためのコマンドを指しています。
これが、レコード処理中(レコード前処理〜レコード後処理)は送出されません。
レコード処理中はコマンドがクライアントのメモリ上に蓄積され、レコード後の後か、タスク後の後に、まとめてDBMSに送られます。
どちらのタイミングなのかは、トランザクション開始の設定によります。
トランザクション開始が「レコード前処理の前」であれば、コマンドの送出は「レコード後の後」ですし、トランザクション開始が「タスク前処理の前」であれば、コマンドの送出は「タスク後の後」です。
いずれにせよ、コマンドが物理トランザクションよりも遅れて出るので「遅延」トランザクションと呼びます。

具体的な動作については、徐々に説明を増やしていきたいと思いますが、まずは、この違いの重要性を認識しておきましょう。
おそらく、遅延トランザクションの方が難解だと思いますので、理解が曖昧な間は、C/Sアプリケーションは物理トランザクションで作成しておいた方が無難だと思います。
オンラインタスクのデフォルトを物理トランザクションにするためには、Magic.iniの設定が必要です。
それについては、こちらを参照してください。
(バッチタスクのデフォルトは物理トランザクションです。)

また、子タスク以下では「W=親と同一」がデフォルトになります。
このままでも構いませんが、「物理トランザクション」を明示する習慣をつけておく方が確実性が増すという意見もあります。
トランザクションモード、トランザクション開始、ロック方式、これらについては全タスクで「指差し確認する」というルールを作っておいても良いかもしれません。