【すなっぷしょっとぶんり】
スナップショット分離 とは?
最終更新:
💡 同じ時点の「写真」を見ながら処理するDBの分離方式
トランザクション内の読み取りで、基準時点のコミット済みデータの版を参照する分離方式。他のトランザクションが後から確定した更新は見えず、自分の更新は見える。
📌 このページのポイント
- 基準時点のデータの版を読む。DB全体を毎回丸ごとコピーするとは限らない
- 通常の読み取りと書き込みの競合を減らせるが、ロックや待ちが一切なくなるわけではない
- 同じ行の更新競合で中断する場合は、トランザクション全体の再試行が必要
- PostgreSQLのRepeatable Readが実装例。SQL ServerのSNAPSHOTは有効化が必要
- 別々の行を更新する書き込みスキューは起こり得る。Serializable等で対処する
スナップショット分離って、どんな仕組みなの?
処理中に同じ基準時点のデータの版を読む仕組みだよ。他のトランザクションが後から確定した更新は見えないけれど、自分が行った更新は見える。PostgreSQLでは最初のデータ操作文の開始時点が基準になるよ。
じゃあ、同時に別の人が書き込んでいても大丈夫なの?
通常の読み取りに、更新を止めるための行ロックを使わずに済むので、読み書きの競合を減らせるよ。ただし書き込み同士の待ちや別のロックはあり得る。「全部ロックなし」「必ず高速」ではないんだ。
自分が書き込もうとしたときは?
普通の分離とどう違うの?
分離レベルの名前と実装を分けて考えよう。PostgreSQLのRepeatable Readはスナップショット分離で、読み取りに共有行ロックを使う実装とは異なる。SQL ServerではSNAPSHOTを有効化し、使う分離レベルを指定する必要があるよ。
じゃあ完璧なの?
別々の行を変える「書き込みスキュー」で、業務ルールを破ることがあるよ。防ぐにはSerializableを使うか、関係する処理で適切なロックなどを使う設計が必要。Serializableでも競合による中断と再試行はあり得るんだ。
もっと詳しく知りたい人へ
書き込みスキューはどんなときに起こる?
「当番は最低1人」という業務ルールで、AとBが両方とも当番の版を読むとする。別々のトランザクションが相手の当番を確認して自分だけを外すと、異なる行の更新なので両方が確定し、当番が0人になることがある。Serializableを使うか、関係する処理すべてで適切なロック等を使い、ルールを守る設計が必要。中断した場合は処理全体を再試行する。
まとめ:ざっくりこれだけ覚えればOK!
「スナップショット分離」って出てきたら「同じ時点のデータの版を見て処理する分離方式」と思えばだいたいOK!
📖 おまけ:英語の意味
「Snapshot Isolation」 = スナップショット分離
💬 snapshotはある時点の状態、isolationは分離。写真は読み取る版の比喩で、実際にDB全体を複製するとは限らないよ。