判断: どの分離レベルか?
トランザクション分離レベルは、同時実行性と一貫性のバランスを決定する。分離レベルが高いほど異常は減るが、ロック/競合とリトライが増える。このツリーは、許容できる読み取り異常 (ダーティ、反復不能、ファントム) に基づき、Read Committed、Repeatable Read/Snapshot、Serializable の中から選択するのに役立つ。
ダーティリードを許容できるか?
最も基本的な異常から始める: トランザクションが、まだコミットされていない (ロールバックされる可能性がある) データを読めてよいか? まともなアプリケーションでこれを望むものはほとんどなく、最新のエンジンの多くはデフォルトでダーティリードを防止する。緩和するのは、概算/分析用の大まかなカウントと最大速度が必要な場合のみ。
- いいえ、コミット済みのデータのみを読む必要がある
- はい、大まかな/概算の読み取りで十分 (まれ)
同じトランザクション内で再読み取りしたときに同じ結果が必要か?
ダーティリードを除外した次の質問: トランザクション内で同じ行を 2 回読んだとき、間に誰かがコミットしたために異なる値が見える (反復不能読み取り) こと、または新しい行が現れる (ファントム) ことは問題か? レポート/計算の一貫性が必要なロジックには、通常、一貫したスナップショットが必要。
- いいえ、各文が最新のコミット済みデータを参照すればよい
- はい、トランザクション全体で一貫したスナップショットが必要
同時実行トランザクションは論理的に完全に順序付けられる必要があるか?
一貫した読み取りを求めているが、それで十分か、それとも同時実行トランザクションが 1 つずつ順番に実行されたかのような結果 (serializable) を生む必要があるか? write skew のような微妙な異常 (例: 2 つのトランザクションが異なる行を読み、互いを無効にする形で書き込む) を許容できるなら Snapshot で十分。そうでなければ完全な直列化が必要。
- いいえ、一貫したスナップショットで十分
- はい、同時実行の異常は一切許容できない
推奨: Read Uncommitted (特殊なケースのみ)
最も低い分離レベルで、ダーティリードを許容する。ロック待機がほぼない状態で読み取れるが、ロールバックされ得るデータが見える可能性がある。汎用アプリケーションには推奨しない。
推奨: Read Committed (OLTP のデフォルト)
各文は、その時点でコミットされた最新のデータを参照し、ダーティリードは防止される。多くのエンジンのデフォルトであり、一般的な OLTP ワークロードに最適な同時実行性/一貫性のバランスを提供する。
推奨: Repeatable Read / Snapshot (一貫した読み取り)
トランザクションは、開始時 (または最初の読み取り時) に固定された一貫したスナップショット上で動作し、トランザクション中に読み取り結果は変わらない。MVCC により、読み取り側は書き込み側をブロックせず、書き込み側も読み取り側をブロックしない。
推奨: Serializable (完全な分離)
最も高い分離レベル: 同時実行トランザクションが、直列に (1 つずつ順番に) 実行されたかのような結果を生む。すべての読み取り異常と write skew を防止する。代償は競合の増加とリトライの必要性。