SQLトランザクション: BEGIN、COMMIT、ROLLBACK
BEGIN、COMMIT、ROLLBACKによるSQLトランザクションをマスター。アトミック操作のための分離レベル、セーブポイント、デッドロック防止戦略を解説します。
Advanced
詳細な説明
SQLトランザクション: BEGIN、COMMIT、ROLLBACK
トランザクションは、単一のアトミック単位として実行されるSQL操作のシーケンスです。すべての操作が成功する(COMMIT)か、すべてが取り消される(ROLLBACK)かのいずれかで、データの一貫性を保証します。
基本構文
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;
いずれかのステートメントが失敗した場合、ROLLBACK を実行してすべての変更を取り消します。
ACID特性
- 原子性(Atomicity): すべてか無か。部分的なトランザクションは永続化されない
- 一貫性(Consistency): データはある有効な状態から別の有効な状態に移行する
- 分離性(Isolation): 同時実行トランザクションが互いに干渉しない
- 永続性(Durability): コミットされたデータはシステム障害後も保持される
セーブポイント
トランザクション内にチェックポイントを作成し、部分的なロールバックを可能にします:
BEGIN;
INSERT INTO orders (customer_id, total) VALUES (1, 100.00);
SAVEPOINT order_created;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
-- これが失敗した場合:
ROLLBACK TO SAVEPOINT order_created;
-- orderのINSERTは保持され、itemsのみがロールバックされる
COMMIT;
分離レベル
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
| レベル | ダーティリード | 反復不可能読み取り | ファントムリード |
|---|---|---|---|
| READ UNCOMMITTED | あり | あり | あり |
| READ COMMITTED | なし | あり | あり |
| REPEATABLE READ | なし | なし | あり(MySQL: なし) |
| SERIALIZABLE | なし | なし | なし |
分離レベルが高いほど一貫性は向上しますが、同時実行性とスループットは低下します。
デッドロック防止
- すべてのトランザクションでテーブルへのアクセス順序を一貫させる
- ロック保持時間を最小化するためにトランザクションを短く保つ
- 必要以上に高くない適切な分離レベルを使用する
- アプリケーションコードでデッドロック時に指数バックオフでリトライする
- 必要に応じて明示的に行レベルロック(
SELECT ... FOR UPDATE)を使用する
エラー処理パターン
アプリケーションコードでは、トランザクション操作の周りに必ずtry/catchブロックを使用し、エラー発生時にROLLBACKが呼ばれるようにしてください。トランザクションを開いたままにすると、ロックが保持され他の操作がブロックされます。
トランザクションはリレーショナルデータベースにおけるデータ整合性の基盤であり、複数の関連操作が一括で成功または失敗する必要がある場合に使用しなければなりません。
ユースケース
銀行アプリケーションが、口座間の資金移動にトランザクションを使用して、引き落としと入金の操作が両方とも正常に完了するか、両方とも完全にロールバックされることを保証する場面。