トランザクション分離レベル
同時実行されるトランザクション間のデータの見え方を制御するデータベースの設定
データベーストランザクション
トランザクション分離レベルとは
トランザクション分離レベルは、同時実行されるトランザクション間でデータがどのように見えるかを制御する設定である。分離レベルが高いほどデータの一貫性は保たれるが、パフォーマンスは低下する。
4 つの分離レベル
4 つの分離レベルを以下にまとめる。
| レベル | ダーティリード | ノンリピータブルリード | ファントムリード |
|---|---|---|---|
| Read Uncommitted | ✅ 発生 | ✅ 発生 | ✅ 発生 |
| Read Committed | ❌ 防止 | ✅ 発生 | ✅ 発生 |
| Repeatable Read | ❌ 防止 | ❌ 防止 | ✅ 発生 |
| Serializable | ❌ 防止 | ❌ 防止 | ❌ 防止 |
異常の種類
異常の種類を図で示す。
ダーティリード:
TX1: UPDATE balance SET amount = 0 (未コミット)
TX2: SELECT amount → 0 を読む
TX1: ROLLBACK → 実際は元の値
→ TX2 は存在しないデータを読んだ
ノンリピータブルリード:
TX1: SELECT amount → 1000
TX2: UPDATE amount = 500; COMMIT
TX1: SELECT amount → 500 (同じ TX 内で値が変わった)
ファントムリード:
TX1: SELECT COUNT(*) WHERE age > 20 → 10件
TX2: INSERT (age=25); COMMIT
TX1: SELECT COUNT(*) WHERE age > 20 → 11件 (行が増えた)
RDS のデフォルト
RDS のデフォルトを以下にまとめる。
| DB | デフォルト分離レベル |
|---|---|
| PostgreSQL | Read Committed |
| MySQL (InnoDB) | Repeatable Read |
| Aurora PostgreSQL | Read Committed |
| Aurora MySQL | Repeatable Read |
DynamoDB のトランザクション
DynamoDB は SQL のトランザクション分離レベルとは異なるモデルを採用する。
await db.transactWrite({
TransactItems: [
{ Update: { TableName: 'accounts', Key: { id: 'A' },
UpdateExpression: 'SET balance = balance - :amount',
ExpressionAttributeValues: { ':amount': 100 } } },
{ Update: { TableName: 'accounts', Key: { id: 'B' },
UpdateExpression: 'SET balance = balance + :amount',
ExpressionAttributeValues: { ':amount': 100 } } },
],
});
// 全操作が成功するか、全操作が失敗する (All or Nothing)
選択の指針
選択の指針を以下にまとめる。
| ケース | 推奨 |
|---|---|
| 一般的な Web アプリ | Read Committed |
| 金融取引 | Serializable or 楽観ロック |
| 分析クエリ | Read Committed (長時間ロックを避ける) |
| 高スループット | Read Committed (ロック競合を最小化) |
基礎から学ぶなら関連書籍が手がかりになる。
この記事は役に立ちましたか?
関連用語
楽観的ロック
データの読み取り時にロックせず、更新時にバージョンを検証して競合を検出する排他制御
DynamoDB
AWS のフルマネージド NoSQL データベースで、ミリ秒単位のレイテンシとシームレスなスケーリングを提供する
REST 成熟度モデル
Leonard Richardson が定義した REST API の成熟度を 4 段階で評価するモデル
ロギング
アプリケーションの動作を記録し、デバッグ・監視・監査に活用する仕組み
ACID
データベーストランザクションの 4 つの特性 - 原子性、一貫性、分離性、永続性
バルクヘッドパターン
システムをリソース的に独立した区画に分離し、障害の影響範囲を限定する耐障害性パターン