トランザクションの管理(FireDAC)
接続の操作(FireDAC) への移動
FireDAC を使って DBMS トランザクションを管理する方法を説明します。FireDAC には、データベース トランザクションを扱うのに役立つ TFDConnection コンポーネントと TFDTransaction コンポーネントが用意されています。
概要
FireDAC アプリケーションは、デフォルトでは、自動コミット モードで動作します。つまり、トランザクションは、必要なときに FireDAC により自動的に開始され、コマンド実行の成功時にコミットされ、失敗時にはロールバックされます。自動コミットは TFDTxOptions.AutoCommit プロパティで制御されます。自動コミット モードはアプリケーションにとっては使いやすいですが、以下のような欠点もあります。
- データベースに対して複数の更新を行うと、実行速度が低下する。
- 単一のトランザクションでより多くのデータベース操作を実行できない。
- 長時間にわたって実行することができない。
あるいは、アプリケーションで明示的なトランザクション制御を使用することもできます。それには、TFDConnection の StartTransaction、Commit、Rollback の各メソッドを使用します。これに代わる方法として、TFDTransaction コンポーネントを使用することもできます。
メモ: TFDTransaction コンポーネントの使用は FireDAC ではオプションとなっています。
FireDAC には、Isolation、ReadOnly、Params の各プロパティが用意されており、これらを使用してトランザクション モードを制御することができます。これらは自動コミット トランザクションにも明示的トランザクションにも適用されます。DBMS ですべてのモードがサポートされているわけではありません。読み取り専用モードがその例です。FireDAC では、より制限の弱いモードを使用しています。なお、すべての設定は次回以降のトランザクションにのみ適用されます。
明示的トランザクションを使用する標準的なコードは以下のとおりです。
FDConnection1.StartTransaction;
try
FDQuery1.ExecSQL;
....
FDQuery1.ExecSQL;
FDConnection1.Commit;
except
FDConnection1.Rollback;
raise;
end;
TFDTransaction コンポーネントは、トランザクション制御機能を 1 つのコンポーネントにラップしたものです。実質的に TFDConnection と同じトランザクション機能を提供していますが、TADTransaction では、コマンドやデータセットを特定のトランザクション オブジェクトにリンクすることでそれらをグループ化することができます。まず、ここでは、InterBase や Firebord サーバーの特長の 1 つである、複数のアクティブ トランザクションのサポートについて触れます。
TFDTxOptions.Params は、DBMS 固有のトランザクション属性を指定するのに使用することができます。目下のところ、そのような属性をサポートしているのは Firebird/InterBase ドライバだけです。属性ごとに別々の行に指定する必要があります。これはトランザクション パラメータ isc_tpb_<属性名> に対応します。
ネストしたトランザクション
FireDAC でサポートしているデータベース管理システムはどれも、ネストしたトランザクションには対応していませんが、FireDAC では、セーブポイントを使ってそれをエミュレートします。つまり、StartTransaction のネストした呼び出しを行っても、新しいトランザクションは開始されず、例外も発生せず、代わりに、セーブポイントが設定されます。DBMS でセーブポイントがサポートされていない場合は、"機能がサポートされていません" という例外が発生します。
ネストしたトランザクションを無効にするには、TFDTxOptions.EnableNested を False に設定します。その場合、StartTransaction のネストした呼び出しを行うと、例外が発生します。
対応する Commit の呼び出しでセーブポイントが解放され、Rollback の呼び出しでセーブポイントまでロールバックされます。以下に例を示します。
// start new transaction
FDConnection1.StartTransaction;
try
FDQuery1.ExecSQL;
....
// set savepoint
FDConnection1.StartTransaction;
try
FDQuery1.ExecSQL;
....
// release savepoint
FDConnection1.Commit;
except
// rollback to savepoint
FDConnection1.Rollback;
raise;
end;
// commit transaction
FDConnection1.Commit;
except
// rollback transaction
FDConnection1.Rollback;
raise;
end;
メモ: ネストしたトランザクションでは、最も外側のトランザクションの設定を使用します。
継続トランザクション
CommitRetaining メソッドおよび RollbackRetaining メソッドは Commit メソッドおよび Rollback メソッドと似ていますが、トランザクションを終了しません。そのため、これらの呼び出しの後もトランザクションはアクティブなままです。Firebird/InterBase サーバーでは、DBMS のコア レベルでこの機能をサポートしています。他のすべてのデータベース管理システムの場合、この機能は Commit/Rollback 呼び出しと StartTransaction 呼び出しを使ってエミュレートされます。
複数のアクティブ トランザクション
Firebird と InterBase では、DBMS のコア レベルで複数のアクティブ トランザクションをサポートしています。つまり、第 1 のトランザクション コンテキストで実行されるコマンドもあれば、第 2 のトランザクション コンテキストで実行されるコマンドもあり、さらにその他のトランザクション コンテキストでもコマンドが実行される可能性があるということです。この機能をサポートするため、FireDAC には TFDTransaction コンポーネントが用意されています。いつでも、その単一のインスタンスで単一のトランザクションを処理することができます。
TFDCustomConnection の以下のプロパティを使用すると、デフォルト トランザクション オブジェクトをセットアップできます。
- Transaction -- すべてのコマンドのデフォルト トランザクション オブジェクト。
- UpdateTransaction -- すべての更新コマンドのデフォルト トランザクション オブジェクト(FireDAC データセットからの更新をポストするのに使用)。なお、UpdateTransaction は、たとえば、TFDQuery コンポーネントに明示的に指定された UPDATE クエリには使用されません。
TFDCustomQuery などのコンポーネントにも、以下のように、類似のプロパティがあります。
- Transaction -- SQL クエリの実行に使用する明示的トランザクション オブジェクト。
- UpdateTransaction -- データセットからの更新のポストに使用する明示的トランザクション オブジェクト。
一般に、Firebird/InterBase アプリケーションのトランザクション オブジェクトをセットアップする最善の方法は以下のとおりです。
UpdateTransaction: TFDTransaction;
ReadTransaction: TFDTransaction;
...
// setup transaction for updating commands: read_committed, rec_version, nowait
UpdateTransaction.Connection := FDConnection1;
FDConnection1.UpdateOptions.LockWait := False;
UpdateTransaction.Options.ReadOnly := False;
UpdateTransaction.Options.Isolation := xiReadCommitted;
...
ReadTransaction.Connection := FDConnection1;
ReadTransaction.Options.ReadOnly := True;
ReadTransaction.Options.Isolation := xiReadCommitted;
...
SelectQuery.Transaction := ReadTransaction;
SelectQuery.UpdateTransaction := UpdateTransaction;
メモ: 他のデータベース管理システムの場合は、複数の TFDTransaction を使用できます。その場合は、すべての TFDTransaction コンポーネントで同じトランザクションを共有します。
トランザクションとカーソル
DBMS では、開いているカーソルを、それが開かれたトランザクション コンテキストに関連付けます。トランザクションが終了すると、DBMS ではアクティブなカーソルを無効にすることができます。詳しい動作は、以下のように、DBMS によって異なります。
DBMS | 動作 |
---|---|
Microsoft Access | StartTransaction/Commit/Rollback が呼び出されたときにカーソルを無効にします。 |
Firebird | Commit/Rollback が呼び出されたときにカーソルを無効にします。 |
Informix | <何もしない> |
InterBase | Commit/Rollback が呼び出されたときにカーソルを無効にします。 |
IBM DB2 | Rollback が呼び出されたときにカーソルを無効にします。 |
MySQL | StartTransaction/Commit/Rollback が呼び出されたときにカーソルを無効にします。 |
Oracle | <何もしない> |
PostgreSQL | Commit/Rollback が呼び出されたときにカーソルを無効にします。 |
SQLite | Rollback が呼び出されたときにカーソルを無効にします。 |
SQL Anywhere | <何もしない> |
SQL SERVER | StartTransaction/Commit/Rollback が呼び出されたときにカーソルを無効にします。 |
Teradata Database | <何もしない> |
FireDAC では、カーソルの無効化につながるトランザクション制御コマンドを検出した場合は、FetchOptions.AutoFetchAll で指定されたアクションを実行し、カーソルを解放します。
メモ: Firebird /InterBase サーバーでは、準備されたステートメントをトランザクションの終了時に無効にします。そのため、これらのデータベース管理システムでは、自動コミット モードにすると、パフォーマンスが低下するおそれがあります。