トランザクション分離レベル - RDB

最終更新日: 2026-08-25

TOP(About this memo)) > 一覧(RDB) > トランザクション分離レベル

トランザクション分離レベル

atomic(不可分性)とisolate(分離性)

ひとつのステートメントは、atomicであり、isolateである(?)。ステートメントはサブクエリを含んでいても、ひとつのステートメントとして扱われる。これはさすがにどのRDBMSでも保証されているはず。

一方、BEGINCOMMITROLLBACK)のトランザクションは、一般的にatomicではあるが、isolateではないので注意が必要。

各異常状態(ANSI定義)

※ ファジーリードとファントムリードは、ネット上の説明が若干わかりづらい(表現に揺れがある)ため、以下は自分なりの言葉で整理している。

各分離レベル(ANSI定義)

MySQLとPostgreSQLの実装の違いは以下の通り。

A Critique of ANSI SQL Isolation Levels

Snapshot Isolation

Anomaly

Anomalyとは、Serializableでない実行を引き起こす異常状態パターンのことを言う。弱い分離レベルほどAnomalyが起きやすい。

ANSI定義にはないAnomalyとして、以下のようなものがある。

MySQLで実験している記事もある。REPEATABLE READでLost Updateが起きているが、Locking READ/WRITEを使えば起きない、とのこと。

MVCCと通常のselect

MVCC(MultiVersion Concurrency Control:多版型同時実行制御)

いつスナップショットを生成するか(PostgreSQL)

古いバージョンのドキュメント(9.4系(?))ではトランザクションの開始前にスナップショットを取得すると書かれていたが、9.5以降のドキュメントからはトランザクション内の最初の読み取り時にスナップショットを取得すると説明されている(?)。

いつスナップショットを生成するか(MySQL)

MySQLではトランザクション内でロック無しSELECTが実行された段階でスナップショットが生成される。ただし、そのスナップショットが違うテーブル・SQLに対してであっても、ロック無しSELECTであれば全て同一のスナップショットが適用されるのかは未確認(TODO)。

CSR(Conflict Serializable)、2PL(2 Phase Lock)、S2PL、SS2PL、C2PL

このあたりの理論はかなり難解で、要点整理はできていない(TODO)。

分離レベルの無難なプラクティス(WIP)

(IMO) READ COMMITEDが良い塩梅だと思っている。REPEATABLE READにする積極的な理由はあまりない(消極的な理由もないが)。単にREAD COMMITED + Locking READ/WRITEのやり方に慣れているのであれば、MySQLでもPostgreSQLでもいずれにせよロストアップデートは対応可能、という理解。

特に SERIALIZABLE についてはチューニングの知識も求められるため,インフラも含めるとかえって学習コストが上がってしまう懸念がある。無理をして使うよりは,素直に READ COMMITTED で Locking Read を用いるほうが汎用性は高い。

補足: 「Locking Read」はREAD COMMITTEDだとファントムリードが起きるが、「勧告的ロック」(ロック概論参照)を使うことでファントムリードに対応できる。

方針として、以下のような形が挙げられる。

PostgreSQL

デフォルトのREAD COMMITTEDのまま使うのが無難。REPEATABLE READやSERIALIZABLEにすることで楽観的制御の恩恵を受けたり、統一的にシリアルにすることができるが、性能チューニング等の独自の学習コストがある。活かせるユースケースもそれほど多くないことを考えると、デフォルトのままが無難(IME)。

MySQL

デフォルトのREPEATABLE READではなく、READ COMMITTEDにするのが無難(IME)。REPEATABLE READにはギャップロックを使っているため、意図しないロックを発生させるおそれがあるという課題がある。

なお、Locking Read/Writeは一貫性読み取りではない。