Site cover image

fhhm’s blog

🫧InnoDBのREPEATABLE READ

トランザクション分離レベル

下記の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の行

これによってトランザクション開始時点のスナップショットからデータを読み取ることができる