こんにちは。@mosuke5です。
少し前のブログに引き続きデータベーススペシャリストの勉強をしてその中で気になったことを調べたのでまとめます。
今回は「隔離性水準」について調べてみました。前回の記事はこちらです。
ACID特性
データベースにはトランザクションが持つべき特性であるACID特性というものを備えています。 ACID特性とは一般に下記の4つの特性のことを指しています。
A | Atomicity | 原始性 |
C | Consistency | 一貫性 |
I | Isolation | 隔離性 |
D | Dirability | 耐久性 |
ACID特性についてはここでは詳しく書かきませんが、その中に隔離性という以下の特性をもっています。
「複数のトランザクションを並行して実行しても直列に実行した時と同じ結果になる。
また、トランザクション実行中は変更前の状態として見える。」
しかし、複数のトランザクションを並列で実行すると、その隔離性を満たさない現象が発生することがあります。
その現象は主に以下の3つです。
1. ダーティリード
[概要]
あるトランザクションの処理中に、別のユーザがそのトランザクションでまだコミットしてないデータを読み込んでしまう現象のことです。
何が問題かというと、例えばそのトランザクションがロールバックしたとすると、存在しない処理のデータを読み込んでいることになってしまうことが発生してしまいます。
[対策]
対策はシンプルで、まだコミットしていないデータは読み込めないようにするだけです。
つまり、データを更新するときは「排他ロック」をかけるようにするということです。
2. ノンリピータブルリード
[概要]
同一トランザクション内で、一度読み込んだデータを再読み込みすると値が異なる現象です。
[対策]
データを読み込むときには「共有ロック」をかけるようにするというものです。
共有ロック中は他トランザクションから更新はできなくなるのでノンリピータブルリードは起きません。
3. ファントムリード
[概要]
あるトランザクションが複数行ある結果を返す検索条件で問合せを2度実行する間に、
コミットされた別のトランザクションによってその条件を満たす新しい行が挿入されたり、削除された行がでたりする現象です。
[対策]
検索結果の範囲に対してロックをかけることです。
上記現象が起こらないようにトランザクションの分離レベルが用意されています。
トランザクションの分離レベルと、現象に発生の有無
分離レベル | ダーティリード | ノンリピータブルリード | ファントムリード |
---|---|---|---|
Read Uncommitted | あり | あり | あり |
Read Committed | なし | あり | あり |
Repeatable Read | なし | なし | あり |
Serializable | なし | なし | なし |
Serializableは最強か
ここでひとつ疑問が湧いてきました。 どの事象も発生しないというSerializableの設定をしてしまえば何も気にしなくていいのだろうか。
残念ながらそう簡単にはいかないのです。
上の「トランザクションの分離レベルと、現象に発生の有無」でいえば、下にいけばいくほど、処理負担が大きく実行スピードが遅くなります。
つまりは、トランザクションの分離レベルと実行スピードはトレードオフになるということです。
そのときの要件や特徴に合わせて分離レベルを選ばなければならないのが現実です。
ちなみに、MySQLのInnoDBではデフォルトはRepeatable Readが設定されています。
まずは標準設定のままでよいと思います。
まとめ
データベーススペシャリストなどの勉強をしているとでてくる「隔離性水準」というものについてみてきました。 教科書上のことだけかとも思っていましたが、実際のMySQLの設定レベルでも設定が可能なものです。 データベース設計をいかにいままで適当にやっていたかなどが身にしみます。
資格勉強だけではなくて現実世界の応用にぜひ活用していきたいです。