🤖
Web+DBシステムでの読み取り整合性の問題とそれが発生しうる3つのレベルの話
DBを含んだWebシステムを構築するとき、書き込んだ直後の結果を読み取ろうとすると問題が起こるケースがあります(いわゆる読み取り整合性の問題)。
このページではそれを整理しています。
※ 経験ベースで一旦列挙したものなので、網羅しきれていなかったり見落としがあるかも
番号が若いほどミクロよりです。
1. DBトランザクションレベル
いわゆるDBのトランザクション分離レベルに関連した話。
dirty read, phantom readなどと言った問題を引き起こします。
これはDBインスタンスが1台のみでレプリケーションを行っていない場合でも発生する問題です。
2. DBクラスターレベル
レプリケーションを行っているDBクラスターで発生する問題です。
こんな感じ:
- マスターインスタンスへinsert
- スレーブインスタンスでその結果をselect
- マスターからスレーブへレプリケーションされる前にselectされた結果、insertした結果が取れない
この問題はレプリケーション設定がある場合のみ問題が発生します。レプリケーション自体が比較的近年多用されるようになったためか、トランザクション分離レベルほど十分な議論がされていません。
これについては、次のような対策が考えられています:
3. リクエストレベル
ウェブアプリケーションで発生する問題です。
こんな感じ:
- クライアントからPOSTやPUTリクエストを通じてDBへ書き込む
- クライアントからGETリクエストを通じてDBから読み取る
- マスターからスレーブへレプリケーションされる前にselectされた結果、insertした結果が取れない
これは前述のstickyオプションなどでは解決できません。
これについては次のような対策が考えられています:
- delay設定: Active Record の複数データベース対応 - Railsガイド
まとめ
Web+DBシステムでの読み取り整合性の問題とそれが発生しうる3つのレベルを紹介しました。
- DBトランザクションレベル
- DBクラスターレベル
- リクエストレベル
重要な点として、これらは前者ほどミクロ、後者ほどマクロではあるものの、どれかを対応すれば他に対応する必要がない、というものではない点です。
リクエストレベルで対応したとしてもDBクラスターレベルで整合性に配慮しないと、問題が発生します。
よりよい機能リリースを目指すのであれば、これらそれぞれへ配慮した実装が必要となるでしょう。
Discussion