メインコンテンツまでスキップ

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

トランザクションとは

RDBMSにおいて、トランザクションはデータベース上で行われる一連の捜査をまとめたものです。 トランザクションは以下の特性を持つことが期待されています。

Atomicity (原子性)

トランザクション内の全ての変更が同時に行われるか、全く行わないかが保証する性質のことです。 つまり"コミット"をすることで全ての変更が行われ終了するか、"ロールバック"を行うことで何も変更を行わず終了することを意味します。

Consistency (一貫性)

トランザクションの前後でデータベースの状態を適切に保つことを保証する性質のことです。 複数のトランザクションが同じデータに対して変更を加えても、どちらの変更も適切に行われ矛盾が生じないようになることを意味しています。 この一貫性を保つためにアクセスのあった行やテーブルなどは一時的にそのトランザクションで"ロック"(他の変更を受け付けないように待機を命令すること)をかけることになります。

Isolation (独立性)

複数のトランザクションが同時に実行される場合に、それらは互いのトランザクション内に影響を及ぼさないことを保証する性質のことです。 各トランザクションは独立したものとして処理され、他のトランザクションの影響で結果を左右されないように

Durability (耐久性)

トランザクションが正常に終了した場合、それによって変更されたデータが永続的に保存され、障害などによってコミット前の状態に戻ることはないように保証する性質のことです。

同時実行性と一貫性

同時実行性はどの程度の変更を同時(あるいはほぼ同時)に処理することができるかの性質です。 これはデータベースがどの程度で変更を完了するかを意味しておりWebシステムを作るにあたって重要な項目だと考えられます。 しかし、データベースにおいて上記のトランザクションの保証する性質における"一貫性"と、"同時実行性"はトレードオフの関係にあります。 一貫性を保つために順次の処理に変更すると同時実行性は下がりますし、同時実行性をあげることで一貫性を保てない変更になってしまうからです。

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

この"一貫性"と"同時実行性"というトレードオフをどの程度"独立性"の面で受け入れて繋ぎ止めるかを決めるのが"トランザクション分離レベル"です。 ある程度、他のトランザクション変更が自身のトランザクションに影響を与えてくることを許容し(あるいは拒否し)、一貫性を犠牲に同時実行性を重視するのかを決めることになります。

MySQLのInnoDBではこの分離レベルが以下の4種類定義されています。

  • Read Uncommitted
  • Read Committed
  • Repeatable Read
  • Serializable

Read Uncommittedが最も同時実行性を高く、一貫性を損なうレベルで、 逆にSerializableが最も同時実行性が低く、一貫性が高いレベルとなります。 MySQLのInnoDBではデフォルトにRepeatable Readが採用されています。

一貫性を損なう現象

実際に一貫性を損なう現象には以下の4つが存在します。

Dirty Read (ダーティリード)

他のトランザクションで行われた、"コミット前の変更"を参照してしまう現象です。 確定していない他トランザクションの変更にも関わらず参照してしまい、 当然この変更はロールバックされることもあるので"一貫性"と"独立性"を著しく欠いた状態になっています。

Fuzzy Read (ファジーリード)

他のトランザクションで"コミットされた変更"が、自身のトランザクション内で参照できてしまう現象です。 これだけ聞くとおかしくないようにも思いますが、selectをするたびに参照する値が変わることは"一貫性"と"独立性"を欠いてしまっているといえます。 Non-Repeatable Read(ノンリピータブルリード)とも呼びます。

Phantom Read (ファントムリード)

他のトランザクションで"コミットされた行の追加"が表示されてしまう現象です。 ファジーリードと同様に、selectするたびに参照できるrowの数が変わることは"一貫性"と"独立性"を欠いてしまっているといえます。

Lost Update (ロストアップデート)

他のトランザクションでコミットされて変更した値を、他のトランザクションがコミットすることで変更される現象です。

トランザクション分離レベルと現象の関係性

上記の現象がトランザクション分離レベルによって起こる、あるいは起こらないことになります。 それが以下の相関図として表せます(MySQLの場合)

分離レベルダーティリードファジーリードファントムリードロストアップデート
Read Uncommited発生する発生する発生する発生する
Read Committed発生しない発生する発生する発生する
Repeatable Read発生しない発生しない発生しない発生する
Serializable発生しない発生しない発生しない発生しない