質問: Rails でトランザクション分離レベルを設定する方法 - Hack Your Design! Springでトランザクション管理 - Qiita
回答: この問題は、それぞれの DBMS においてどのように Concurrency を制御する設計になっているのか、に依存します。ひとまず自分の知っている PostgreSQL と MySQL について回答します。 MySQL について ========== MySQL は、更新系のクエリ(Insert/delete/update)と参照系のクエリ(select)において、論理的な作用対象が違います。 MySQL は MVCC を採用していますが、おおむね、 * select: MVCC で snapshot を取れるようにして、それに対して取得する。 * 更新系: 上記の snapshot にかかわらず、その時の buffer pool の最新の値を更新しにかかる。更新されたテーブル(の箇所)は write lock される。 です。また、これを前提として、各 isolation level は、 select がどのように行われるか、の差異しかありません。 * READ UNCOMMITTED: その時点のバッファプールの最新の値を取得する * READ COMMITTED: Tx 内のその文を実行する直前(Txの最初ではなく)の snapshot を読み取る * REPEATABLE READ: Tx 開始時点 * SERIALIZABLE: すべての select を select for update に書き換えて実行。この意味で strict 2 phase commit と同じであり、 lock が取れなければ実行できない PostgreSQL について =============== snapshot isolation を基本に動作する。参照: 端的に言うと、データ参照はデータベースのある時点の snapshot に対して動作し、データ更新系は早い者勝ちで、遅かった方が abort されます。 * READ UNCOMMITTED: 存在しない。READ COMMITTED と同じ動作になる。 * READ COMMITTED: 各文それぞれが単一の Tx であったような動き方をする。 * REPEATABLE READ: Tx の最初のデータ操作・参照の直前を snapshot として、それに対してデータは取得される。 * SERIALIZABLE: ^ に加えて、 serializable を実現するために、 serializable Tx 同士の、同一データに対する read-write 関係を監視して、それが循環すると serializable でなくなる可能性が高いのでどちらか一方を rollback + ^ の理論をまとめた元論文: まとめると ===== PostgreSQL や MySQL は、 MVCC / Snapshot Isolation を実現しており、 isolation level が効いてくるのはどのようにデータを取得するのか、という点において。 MVCC において、データ取得は snapshot に対して実行されるため、 isolation level の組合せによる挙動の制御、というものはあまり存在せず、各 Tx が concurrent にデータを更新していく中でどの時点の snapshot を参照するのか、という違いが主。 ただし、 serializable は snapshot isolation のみでは実現できないため (write skew / read only skew)、 * MySQL では read でも lock を取得し、 * PostgreSQL では serializable 同士の rw の依存関係の監視を行う。