トランザクション分離レベルの違いをわかりやすく

毎回「なんだっけ」ってなるのでメモ。

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

トランザクションを複数同時に実行するとき、「どれだけ影響を分離させるか?」の設定のこと。

SERIALIZABLE (シリアライズ可能)

「絶対に分離する」なレベル。

たとえば、トランザクションAとトランザクションBを同時に実行しているとき、「Aでデータを読み取り/変更(追加/削除/更新)すると、それらのデータはAが終わるまでBで一切処理できない」になります。

REPEATABLE READ (リピータブル・リード)

SQLのデフォルト。

このモードだと、ファントムリードという現象が発生します。

  • ファントムリード:
    トランザクションAとトランザクションBを同時に実行しているとき、Aでデータを追加/削除してコミットすると、Bのほうでも反映されちゃう現象

SERIALIZABLEと違ってデータの読み取りだけではロックされません。たとえば「Aでデータを読み取りすると、それらのデータはAが終わるまでBで一切処理できない」にはなりません。読み取りは許されます。

SERIALIZABLEには以下のように書かれているからです👇

SERIALIZABLEは REPEATABLE READ と似ていますが、autocommit が無効になっている場合、InnoDB はすべてのプレーン SELECT ステートメントを SELECT ... FOR SHARE に暗黙的に変換します。

引用:https://dev.mysql.com/doc/refman/8.0/ja/innodb-transaction-isolation-levels.html

READ COMMITTED (コミット読取り)

このモードだと、ファントムリードに加えて、ファジーリードという現象も発生します。

  • ファジーリード:
    トランザクションAとトランザクションBを同時に実行しているとき、Aでデータを更新してコミットすると、Bのほうでも反映されちゃう現象

ファントムリードと違うのは、追加/削除ではなく更新という点。

たとえば、トランザクションBの最初で👿さんの預金残高を読み取ったら1万円だった。でもトランザクションBを処理中にトランザクションAによって残高が0円に変更された。そしてトランザクションBが終わるころにもう一度👿さんの預金残高を読み取ったら0円になってた。

・・みたいなことがおこる。

要するに、おいおい1万円ある前提で処理を進めちゃったじゃん!みたいなことが起こり得る。

READ UNCOMMITTED (非コミット読取り)

「ぜんぜん分離しない」なレベル。

このモードだと、さきほどの

  • ファジーリード
  • ファントムリード

に加えて、ダーティリードと呼ばれる現象も発生します。

  • ダーティリード:
    トランザクションAとトランザクションBを同時に実行しているとき、Aでコミットしていない変更を、Bで読み取れてしまうヤバイ現象

「ロールバックしたときどうするんだ」って感じですし、どういうシーンで使うんだろう。

おわり

SQL
スポンサーリンク
この記事を書いた人
penpen

1991生まれ。WEBエンジニア。

技術スタック:TypeScript/Next.js/Express/Docker/AWS

フォローする
フォローする

コメント

タイトルとURLをコピーしました