はじめに
こちらの続きです。
同時実行制御
並行して実行されているトランザクションを処理するための技術。大まかに以下に分類できる。
- 楽観的同時実行制御
- Optimistic Concurrency Control / OCC
- 複数のトランザクションは互いにブロックすることなく、お互いの処理がコミットされる際に競合の有無をチェックする。
- 競合があった場合には、一方の処理が中断させられる。
- マルチバージョン同時実行制御
- Multiversion Concurrency Control / MVCC
- レコードにタイムスタンプが異なる複数バージョンの存在を許容し、過去のあるタイミングにおける一貫性の取れた参照を提供する。
- 悲観的または保守的同時実行制御
- Pessimistic Concurrency Control / PCC
- 以下2つに分類
- ロックベース
- トランザクションはレコードに対するロックを管理する必要がある。
- ロックなし
- 読み取り操作と書き込み操作のリストを管理し、終了していないトランザクションのスケジュールに応じて操作を制限する。
- ロックベース
直列化可能性
一連のトランザクションを実行するために必要な操作のリストをスケジュールという。
あるスケジュールで、その中の各トランザクションが完全に独立して連続的に実行される場合、シリアルであるという。(すべての先行するトランザクションが実行された後で次のトランザクションが開始するような実行)
この場合、システムのスループットが著しく低下し、パフォーマンスを損なう。
パフォーマンスを損なうという問題から、シリアルなスケジュールの正確性と単純性を維持しつつ、トランザクションを並列に実行する必要性が生まれる。
トランザクションの分離
いつどのようにしてトランザクションの各部分(途中経過など)を可視化するか、を指定するものとして分離レベルが定義される。
トランザクション分離レベルの定義に応じた読み取り・書き込みのアノマリー(異常)として、以下が想定される。
読み取り書き込みのアノマリー
- ダーティリード
- あるトランザクションでコミットされていないの変更を、別のトランザクションが参照できる
- ノンリピータブルリード
- あるトランザクションが同じ行への問い合わせを2回行い、それぞれで異なる結果を得る
- あるトランザクションが行を読み取り、そのトランザクション内でもう一度読み取るとする。
- 1回目の読み取りと2回めの読み取りの間に、別のトランザクションがその行を修正してコミットしていた場合、読み取りの結果が異なる。
- ファジーリードと呼ばれる場合もある
- あるトランザクションが同じ行への問い合わせを2回行い、それぞれで異なる結果を得る
- ファントムリード
- トランザクション中に範囲読み取りを使用した場合に発生
- トランザクションが同じ行のセットを2度要求し、異なる結果を受け取る
- ロストアップデート
- 2つのトランザクションが同一の値を読み取ったとする。
- 先のトランザクションが値を更新してコミットし、後のトランザクションも値を更新してコミットする。
- このとき、先に更新した値は後の更新で上書きされる。
- ダーティライト
- ダーティリードした値を更新してコミットする。
- ライトスキュー
- 個々のトランザクションは必要な要件を満たしているが、組み合わせで要件を満たさなくなる。
- 2つのトランザクションが、2つの口座の値を変更する状況を考える。
- それぞれの口座残高は$100と$150とする。
- 要件は、これらの合計が負の値にならないことであるとする。
- 個別の口座残高が負になることはOK
- このとき、それぞれの口座から$200引くことを試みる
- それぞれのトランザクション開始時点では$100 + $150 = $250であることから、どちらの口座も$200引くことができる。
- それぞれのトランザクションをコミットした後にはそれぞれ-$100と-$50となり、要件を満たさなくなる。
- 個々のトランザクションは必要な要件を満たしているが、組み合わせで要件を満たさなくなる。
分離レベル
- read uncommited(未コミット読み取り)
- 最も弱い分離レベル
- ダーティリードが許容される
- read commited(コミット済み読み取り)
- ダーティリードは許容されない
- ファントムリード、ノンリピータブルリードは許容される
- repeatable read(反復可能な読み取り)
- ダーティリード、ノンリピータブルリードは許容されない
- ファントムリードは許容される
- serializability(直列化可能性)
- 複数のトランザクションがシリアルに実行されたかのように、結果が特定の順序で現れることが保証される。
- ダーティリード、ノンリピータブルリード、ファントムリードが許容されない
※ MySQLのInnoDBでは、repeatable read でのファントムリードが許容されなかったりするので、DBによって差異はあることに注意
楽観的同時実行制御
トランザクションの競合がめったに発生しないことを前提としたもの。
マルチバージョン同時実行制御
複数のレコードバージョンを許容する。単調に増加するトランザクションIDやタイムスタンプを使用してトランザクションの一貫性を保つ。
悲観的同時実行制御
実行中にトランザクションの競合を特定してそれらの実行をブロックまたは中断する。
最も単純な考え方の一つとして、タイムスタンプによる順序付けがある。(トランザクションがそれぞれタイムスタンプを持ち、より早いタイムスタンプを持つトランザクションがコミットしているかで、実行可否を決定する。)