トランザクション分離レベルと、各レベルで出てくる問題を整理する。
トランザクション分離レベル
まず、トランザクション分離レベルは4段階あり、「READ UNCOMMITED」→「READ COMMITED」→「REPEATABLE READ」→「SERIALZABLE」の順にトランザクションの独立性が高くなっていく。
じゃあSERIALIZABLEにすれば良いのではと思われるかもしれないが、一般にパフォーマンスとのトレードオフであることに注意を払う必要がある。
トランザクション分離レベルと発生しうる問題
以下ではトランザクション分離レベルの簡単な説明と、そのレベルでどのような問題が起きるかを解説していく。上のレベルで発生する問題は下のレベルでも発生する。
SERIALIZABLE
SERIALIZABLEは最も高い分離レベルであり、トランザクションは直列化可能である。直列化可能ということは複数のトランザクションが実行されていてもそれぞれが順番に実行されたように見えるということであり、トランザクションは実行中の他のトランザクションに影響を与えることはない。SERIALIZABLEは特に独立性に関する問題を起こしません。
REPEATABLE READ
REPEATABLE READは2番目に高いトランザクション分離レベルである。同一トランザクション内で複数回の読み込みを行った時に他のトランザクションによって追加、削除されたデータが混入することがある。これをファントムリードと呼ぶ。MySQLのデフォルトの分離レベルはこれである。なお、MySQLではMVCC(MultiVersion Concurrency Control)によってファントムリードを防ぐことができる。
MVCCとは
簡単に説明すると自分より後に発行されたトランザクションの変更を読み取らないようにするために以下の2つを行っている。 -レコードにトランザクションIDを記録する - 更新、削除されるデータを取っておいて後からでも参照できるようにする。
以下が分かりやすかった。 sairoutine.hatenablog.com
READ COMMITTED
3番目に高いトランザクション分離レベル。このレベルではコミットされていないトランザクションの読み取りからは保護されるが、ノンリピータブルリード(ファジーリードとも呼ばれる)が発生する。ノンリピータブルリードでは同一トランザクションで同じレコードを複数回読んだ時に異なる結果が返ってくることがある。
READ UNCOMMITTED
最も低い分離レベルである。コミットされていない変更を他のトランザクションから読みとれてしまう(ダーティリード)。