トランザクション分離レベル
下記の4種類
- READ UNCOMMITTED
- 他のトランザクションでコミットされていない変更も読み取る
- → ダーティーリード
- 他のトランザクションでコミットされていない変更も読み取る
- READ COMMITTED
- 他のトランザクションでコミットされた変更も読み取る
- → ファジーリード(update), ファントムリード(insert, delete)
- 他のトランザクションでコミットされた変更も読み取る
- REPEATABLE READ
- 基本的に他のトランザクションでコミットされた変更を読み取らない
- ただし、insert, deleteは読み取る場合もある
- → ファントムリード
- InnoDBではREPEATABLE READでファントムリードは発生しない
- SERIALIZABLE
- ダーティーリード、ファジーリード、ファントムリードが起きない
ファジーリードとファントムリードの違いは、既存の行に対する更新か行の挿入/削除かだと理解したが、REPEATABLE READでファジーリード防げるならファントムリードも防げるのでは?他のDBと違ってInnoDBではなぜ防げるのか?が気になった
InnoDBにおけるREPEATABLE READ
- 行は
作成バージョン
と削除バージョン
を持っている - 行を変更や削除をする場合、そのトランザクションが持つバージョンで行のバージョンが更新される
- REPEATABLE READではSELECT時に、特定のバージョン以下の行(値)を読み取る
- これがスナップショットと表現される
バージョンがどのように更新されるか
INSERT
- INSERTを行うトランザクションが持つバージョンが行の
作成バージョン
となる
DELETE
- DELETEを行うトランザクションが持つバージョンが行の
削除バージョン
となる
UPDATE
- UPDATE対象行をコピーして新しい行を作成する
- 古い行の
削除バージョン
にUPDATEを行うトランザクションが持つバージョンをいれる - 新しい行の
作成バージョン
にUPDATEを行うトランザクションが持つバージョンをいれる
- 古い行の
SELECT時には下記が読み取られる
- 自分のトランザクションのバージョンより古い
作成バージョン
を持つ行 - 自分のトランザクションのバージョンより新しい
削除バージョン
を持つ行- i.e. 将来削除されるが、SELECT時点ではまだ削除されていない行
削除バージョン
がNullの行
これによってトランザクション開始時点のスナップショットからデータを読み取ることができる