トランザクション分離レベル
複数のトランザクションが同時に実行されたとき、互いの変更がどこまで見えるかを定める設定。SQL標準では4段階定義されているが、PostgreSQLは3段階(Read Committed / Repeatable Read / Serializable)を実装しており、いずれも内部的にはMVCCのスナップショット機構で実現されている。
#database #postgresql #transaction
Read Committed(デフォルト)
トランザクション内の各SQL文が、その文を実行した時点でコミット済みのデータだけを見る。文が実行されるたびにスナップショットを取り直すため、同じトランザクション内でも文ごとに見えるデータが変わりうる。
Repeatable Read
Read Committedと違い、トランザクション内で最初にSQL文を実行した時点のスナップショットを、トランザクションが終わるまで使い続ける。これによりダーティリード・非再現リードは防げるが、PostgreSQLのMVCC実装の性質上、限定的なファントムリードは起こりうる。
Serializable
最も厳格な分離レベル。すべてのコミット済みトランザクションを、あたかも一つずつ順番に(serialに)実行したかのように振る舞わせる。PostgreSQLの実装はSerializable Snapshot Isolation(SSI)と呼ばれ、既知の異常動作すべてに耐性を持つことを目指している。
MySQL(InnoDB)との違い
デフォルトの分離レベルが異なる。PostgreSQLはRead Committedがデフォルトなのに対し、MySQLのInnoDBはRepeatable Readがデフォルト。設計思想の違いとして、MySQLは初期状態からより強い分離レベルを提供する方向、PostgreSQLはより高い並行性を優先する方向とされる。
ファントムリードへの対処方法も異なる。PostgreSQLはMVCCのスナップショット機構だけでファントムリードに対処するため、Repeatable Readでも限定的にファントムリードが起こりうる。一方InnoDBのRepeatable Readは、MVCCに加えてgap lock・next-key lockという行間ロックを併用しており、多くのケースでファントムリードそのものを防いでいる。つまり同じ「Repeatable Read」という名前でも、内部の実現方法(ロックの有無)が異なる点に注意が必要。