トランザクション完全ガイド:ACID・隔離レベル・MVCCから2PC/Sagaまでの分散設計と実務対策
トランザクションとは何か — ITにおける基本概念
トランザクション(transaction)は、データベースや分散システムにおける「一連の処理をひとまとまりとして扱う単位」を指します。一般には「全部成功するか全部取り消す(ロールバック)か」の原則で扱われ、システムの整合性を保つための基本的な仕組みです。トランザクションは単なるデータ更新操作だけでなく、メッセージングや分散サービス間の協調処理にも適用されます。
ACID特性 — トランザクションの4原則
- Atomicity(原子性):トランザクション内の処理は「全体として」成功するか、失敗したら何も反映しない(すべて取り消す)こと。
- Consistency(一貫性):トランザクションの開始前と終了後で、データベースの定義した整合性制約が保たれること(外部キー制約やアプリケーション固有ルールなど)。
- Isolation(独立性):同時に実行されるトランザクション同士が互いの中間状態を見ないこと。隔離レベルによって現れる現象(ダーティリード等)が異なる。
- Durability(耐久性):トランザクションがコミットされたら、その結果は永続化され、障害が起きても保持されること。
SQLでの基本操作
代表的なRDBMSでは、次のような命令でトランザクションを操作します。
- BEGIN / START TRANSACTION — トランザクション開始
- COMMIT — 正常終了として確定(永続化)
- ROLLBACK — 異常終了として取り消し
実際のSQLやAPIでは自動コミットモード(1文ごとに自動的にコミット)を無効にして明示的にトランザクションを制御することが多いです。
隔離レベル(Isolation Levels)と現象
SQL標準では主に以下の隔離レベルが定義され、データ整合性と並行性のトレードオフを表します。
- READ UNCOMMITTED:最も緩く、ダーティリード(未コミットデータの読み取り)を許す可能性がある。
- READ COMMITTED:他のトランザクションがコミットした更新のみを読む。ダーティリードを防ぎ、非反復読(non-repeatable read)やファントムは起こり得る。
- REPEATABLE READ:同一トランザクション内で同じSELECTが繰り返し同じ結果を返すことを保証(ただしDBMSの実装差で意味合いが異なる)。
- SERIALIZABLE:理想的にはすべてのトランザクションが逐次実行されたかのように振る舞う。最も強い整合性を提供するが性能コストが高い。
「ダーティリード」「非反復読」「ファントム」などの現象がどの隔離レベルで防がれるかは標準と実装に依存します。多くの実装はマルチバージョン同時実行制御(MVCC)を用いており、PostgreSQLやMySQL InnoDBなどはそれぞれの方法で隔離レベルを実現しています。
並行制御:ロック vs MVCC(楽観的/悲観的制御)
並行実行を安全に行うための代表的な手法は次の通りです。
- 悲観的ロック(Pessimistic Locking):更新前にロックを取得し、他者の干渉を防ぐ(例:SELECT ... FOR UPDATE)。競合が多い場面で有効。
- 楽観的制御(Optimistic Concurrency Control):トランザクション終了時に整合性を検証し、競合があれば再試行する。バージョン番号やタイムスタンプで実現されることが多い。
- MVCC(Multi-Version Concurrency Control):各トランザクションはスナップショットを読み、更新は新しいバージョンとして書く方式。読み取りと書き込みの競合を減らす。
分散トランザクションとその課題
データが複数のノードやサービスにまたがる場合、単一のACIDトランザクションで管理するのが難しくなります。代表的な手法は次のとおりです。
- 2フェーズコミット(2PC):コーディネータが参加者に準備(prepare)→コミット/ロールバックを指示する。原子性を保証できるが、ネットワーク障害でブロックする問題(同期的に待つ)や可用性低下が起きうる。
- 3フェーズコミット(3PC):2PCの改善版だが、現実の分散環境では完全な解決になりにくい。
- コンセンサス(Raft/Paxos):レプリケーションや分散合意のために用いられる。トランザクションの分散合意にも応用されるが、実装は複雑。
- Sagaパターン(補償トランザクション):長時間の分散ワークフローを小さなローカルトランザクションの連続として扱い、失敗時は補償操作で整合性を回復する(最終的に整合する=eventual consistency)。マイクロサービス環境で一般的。
イベントソーシング・買収整合性(Eventual Consistency)との関係
トランザクションの強い一貫性(強整合性)を保つとスケールや可用性に制約が出ます。イベントソーシングやCQRS、メッセージングを組み合わせることで、各サービスがローカルにACIDを保ちながら、最終的に整合する(eventual consistency)設計が増えています。こうした設計では、補償ロジック、再試行、冪等性(idempotency)が重要です。
実務上のベストプラクティス
- トランザクションは短く保つ:ユーザー入力待ちや長い処理をトランザクション内にしない。
- 適切な隔離レベルを選ぶ:必要以上に高い隔離レベルを選ぶとスループットが低下する。
- 再試行と冪等性を設計する:ネットワーク障害や競合での再試行を安全に行う。
- 分散トランザクションは慎重に:2PCは便利だが可用性やスケーラビリティに影響する。代替としてSagaなどのパターンを検討する。
- 障害対策(Durability):WALやfsyncなど永続化の仕組みを理解し、運用で設定(例:同期コミット)を見直す。
- 監視と死活監査:長時間ロックやデッドロックの検出とアラートを用意する。
よくある誤解
- 「トランザクション = すべての整合性問題を解決する」ではない:分散環境では設計上の妥協(整合性対可用性のトレードオフ)が必要。
- 「Serializableは万能」でもない:実装によってはスループット低下や論理的な書き込み競合(write skew)が起きうる。
- 「トランザクションは重い」:用途によっては軽量なローカルトランザクションで十分。問題は設計次第。
まとめ
トランザクションはデータ整合性を保つための基本的かつ重要な概念であり、ACIDや隔離レベル、並行制御の理解が必須です。単一データベース内でのトランザクションは成熟した技術ですが、分散システムやマイクロサービスでは2PCやSaga、イベントソーシングといった代替手法が必要になります。実運用では、性能と可用性、整合性のバランスを取りながら、短いトランザクション、冪等性の確保、監視・リトライ設計を重視してください。
参考文献
- ACID — Wikipedia
- PostgreSQL: Transaction Isolation
- MySQL :: InnoDB transactions
- Two-phase commit protocol — Wikipedia
- Saga pattern — microservices.io (Chris Richardson)
- Designing Data-Intensive Applications — Martin Kleppmann (O'Reilly)
- Transaction Isolation Levels — Microsoft Docs
- Write-ahead logging — Wikipedia
- Event Sourcing — Martin Fowler


