LoginSignup
36
22

More than 5 years have passed since last update.

Isolation Levelの階層

Last updated at Posted at 2016-12-15

ACIDの中でIsolationは特に蔑ろにされがち、と昨日の記事に書いたが具体的にどのように蔑ろにされるかについて詳しく説明する。

ANSI規格

米国国家規格協会、いわゆるANSIではトランザクションの分離レベルが4つ定められている。

  • READ UNCOMMITTED: 未コミットの値を読む事がある(Dirty Read Anomaly)
  • READ COMMITTED: コミット済みの値しか読まないが、1つのトランザクションの中で複数回同じ値を読みにいった時に外のトランザクションによって更新された最新の値を読んでしまって一致しない事がある(Non-Repeatable Read Anomaly)。また、読んだ値に後から書き込む際に他のトランザクションによって更新された値であっても更にその上から上書きしてしまい過去の更新が消失する(Lost Update Anomaly)。また、2つの値を読む際に1つめを読んだ直後に別のトランザクションによって両方の値が書き換えられても、そのまま2つめの値を読んでしまう(Inconsistent Read AnomalyもしくはRead Skew Anomalyとも言う)
  • REPEATABLE READ: トランザクション内で一度読んだ値を再度読む際も同じ値であることが保証されるが、範囲検索を2回行った時に、1度目のスキャンの後に新たに挿入された値を2度目のスキャンで発見することがある(Phantom Read Anomay)
  • SERIALIZABLE: 上記のAnomalyがすべて起きない

ここまではそこら辺でググっても日本語の情報が豊富に見つかるので大して意外性はない。
図に包含関係をまとめて、個々の丸の中に発生しうるAnomalyを記述するとこうなる。

anomaly.png

歴史上の話を調べてみると、ANSIのこの分離レベルは制定当初2 Phase Lockが基本だった時代背景があり、それでは遅すぎるから2PLを緩和する方向で策定したようである。
そういう観点で見るとこの4レベルからは意図されたLockのプロトコルが透けて見える。

  • READ UNCOMMITTED: Write時のWrite-LockだけS2PLを守って獲得・解放する。Readに際して一切ロックを取らない、Write-Lockが取られている値も平気でReadする(Write同士しか並行制御しない)
  • READ COMMITTED: Write時のWrite-LockだけS2PLを守って獲得・解放する。Read-LockはRead操作1つごとに獲得するが即解放を行ってよい。
  • REPEATABLE READ: Read/Write両方でS2PLを守って獲得・解放する。
  • SERIALIZABLE: Read/Write両方と更に範囲検索に対してはGap Lockを取る。

当然、ロックプロトコルの設計は実装者の手に委ねられているが、仕様をよく読むと意図された実装が透けて見えるのはありがちな話である。

Snapshot Isolation

上に書いた分離レベルの他にアカデミックな分野から出てきた分離レベルがSnapshot Isolationである。
実装としてはMulti Version Concurrency Control(MVCC)にタイムスタンプでの制約を加えて云々というのが一般的のようだが詳細は様々ある。
このIsolation LevelではWrite Skew AnomalyRead Only Anomalyが発生する一方で、Phantom Read Anomalyは発生しない。

つまり、階層関係を整理した図に書くならこのようになる

anomaly2.png

どちらもREAD COMMITTEDより強いが、相互に起きるAnomalyが違うので、完全な包含関係になってはいない。このあたりの話はHal BerensonらのA Critique of ANSI SQL Isolation Levelsの中にまとまっている。

少しおもしろいのが、このANSI規格でのSERIALIZABLEとは、このアドベントカレンダーの冒頭あたりで説明したSerializableと別物であり「REPEATABLE READの上で更にPhantom Readが起きないならSERIALIZABLE」と定義されているため、ANSI規格ではSnapshot IsolationはPhantomが起きないゆえにSERIALIZABLEである。OracleDBのいうSERIALIZABLEはANSI規格のSERIALIZABLEで実質はSnapshot Isolationである。
一方でMySQLではREPEATABLE READであってもファントムリードは発生しない実装になっているらしいのでその基準ではSERIALIZABLEと呼びうる。
つまり、実装・規格・アカデミックのそれぞれで言葉が一緒でも分類が違うので、これらの用語を使う際にはよく注意しないといけない。

調べてみるとWeb開発者が知っておくべき八つの分離レベル等でより多くの分離レベルについて議論されているがここの解像度を深追いしてもややしょうがないような気がしている。

個々のAnomalyに関しては今日の記事では深い言及をしなかったが、そこは明日書く。

36
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
22