復数のトランザクションが同時に実行されるとき、それらのトランザクションがどのように相互作用するかを定義するのが分離レベル。
本来は直列実行すれば並行で実行することの問題が解決できるが、サービスは複数人が同時に使うのが一般的なのでアプリケーション全体のパフォーマンスを考えるとそれは現実的じゃなさそう。(「誰かが実行中なのでお待ちください。」はやばい)
問題に対し、ある部分に関しては許容する。と段階的に定義しているものがトランザクション分離レベル。
PostgreSQLのデフォルトのトランザクション分離レベルは「リードミコッティド」
リードコミッティドの場合、以下の3つが発生しうる。
ダーティーリードは起きない。
一度読み取ったデータを他のトランザクションが変更することで、同じデータを読み取ったとしても異なる値が読み取られること。
トランザクションが複数行のある集合を返す検索条件で問い合わせを行ったあと、別のトランザクションのコミットが行われることで、同じ検索条件で問い合わせを行ったとしても異なる行が返されること。
復数のトランザクションがコミットされたあとの結果が、トランザクションを直列化した場合の結果と異なること。(=直列で実行した場合は正常に値が反映されるが、並列で実行した場合は異なる値になること)
PostgreSQLでは、トランザクション分離レベルをリードアンコミッティド(デフォルトのひとつ下で、もっとも下のレベル)にしたとしても、ファントムリードが発生しない。つまりほかトランザクションのコミット前のデータを読み取ることがない。
上記の挙動をするため、他トランザクションでコミットされるデータを読み取らず、自トランザクションでコミットしようとしたときに、Unique制約に引っかかったことがある。(自トランザクションのコミットは他トランザクションのあと)
トランザクション分離レベルと発生しうる問題を理解していると当然の挙動と理解できる。