トランザクション分離レベル
基本4つ:
Read uncommitted
Read committed
Repeatable read
Serializeable
table:表
分離レベル ダーティーリード ノンリピータブルリード ファントムリード
Read uncommitted 可 可 可
Read committed 不可 可 可
Repeatable read 不可 不可 可
Serializable 不可 不可 不可
挙動は MySQL(InnoDB), PostgresSQL など実装によって異なる場合もある
リピータブルリード分離レベルの場合、ファントムリードは「許容されるが、PostgreSQLでは発生しない」
本来であればトランザクション分離レベルが REPEATABLE READ 以下のときに生じる。 しかし、MySQL の InnoDB では REPEATABLE READ でも例外的にファントムリードが生じない
一方のトランザクションでのコミット前の変更が、もう一方のトランザクションで見えてしまう
e.g.
Tx.a Begin; -> update 1レコード; (not Commit;)
Tx.b Begin; -> select 1レコード; -> 結果セットに反映される
一方のトランザクションでのコミット後のレコード変更が、もう一方のトランザクションで見えてしまう
e.g.
Tx.a Begin; -> update 1レコード; -> Commit;
Tx.b Begin; -> select 1レコード; -> 結果セットに反映される
一方のトランザクションでのコミット後のレコードの追加・削除が、もう一方のトランザクションで見えてしまう
e.g.
Tx.a Begin; -> delete 1レコード; -> Commit;
Tx.b Begin; -> select *; -> 結果セットにレコードが存在
複数のトランザクションで並列に更新が行われた際に、あとで実行された結果が後勝ちしてしまう
e.g.
Tx.a Begin;
-> select num from demo where id = 1;
Tx.b Begin;
-> select num from demo where id = 1;
-> update demo set num = 20 where id = 1;
-> Commit;
Tx.a Begin;
->update demo set num = 99 where id = 1;
-> Commit;
Tx.b の更新はなかったことになる
repeatable read の場合に起こる。tkdn.icon 再現が難しいな
read commited の場合には発生しない
repeatable read でも select ... for update で排他ロックを取ることで一方のトランザクションを待たせることができる