要件をより明確に定義する必要があります。「ネストされたトランザクション」はあいまいです。これは、別のトランザクションを実行するために 1 つのトランザクションを単純に中断し、最初のトランザクションを再開することを意味します。
transactionManager.begin();
// now in tx A
transaction txA = transactionManager.suspend();
// no tx active here
transactionManager.begin();
// now in tx B
transactionManager.commit(); // tx B ends
// no tx active here
transactionManager.resume(txA);
// now in tx A again
transactionManager.commit(); // tx A ends
これは、外部トランザクションから論理的に分離された、監査ログの更新などの操作を実行する必要がある場合に一般的です。TM をそれほど直接的に駆動するコードを記述することはめったにありませんが、どのトランザクション マネージャーもこれを行います。代わりに EJB コンテナーを使用してください。
次に、ロジックの構造化を簡単にするために疑似ネストが必要な場合があります。
// no tx active at start
transactionManager.begin();
// tx A now active, nesting count = 1
transactionManager.begin();
// tx A still active, nesting count = 2
transactionManager.commit();
// nullop, tx A still active, nesting count = 1
transactionManager.commit();
// tx A really committed, no tx active, count = 0.
これは一見魅力的に見えますが、ネストされたロールバックが発生すると、必要以上に手間がかかります。一部のデータベースではストアド プロシージャの処理が容易になりますが、広くはサポートされていません。
最後に、サブトランザクションがその親からロックを継承し、完了時にその親に独自のロックを渡す真のネストされたトランザクションがあります。
transactionManager.begin();
// now in tx A1
transactionManager.begin();
// now in tx A1.1
// can see uncommitted changes made by A1
transactionManager.commit(); // validate ability to make A1.1 changes permanent, but do not actually do so yet
// now in tx A1, still holding locks from A1.1 also
transactionManager.commit(); // commit A1 and A1.1 changes atomically.
これは主に障害分離に役立ちます。外部トランザクションに影響を与えることなく、サブトランザクションをロールバックして代わりに別のことを行うことができます。これは非常に強力なトランザクション モデルです。実装するのもトリッキーです。現在、JBossTS のみがサポートしています。データベースやメッセージ キューなどのリソース マネージャでサポートされていないため、ほとんどの Java EE ユース ケースであまり役に立たないというわけではありません。
MVCC に関しては、トランザクション マネージャーとはまったく関係ありません。ビジネス データはリソース マネージャー (通常はリレーショナル データベース) に保持されます。RM が tx の分離と同時実行制御を提供するために使用するモデルは、トランザクションの駆動方法と直交しています。Oracle と postgres は MVCC を支持しますが、他の一部のデータベースはテーブル、ページ、または行レベルのロックを支持します。トランザクション マネージャは知らないか気にしません。