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

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

よくトランザクション管理と呼ばれるが、このトランザクションがそれぞれでどのぐらい独立性があるかという話。

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

SERIALIZABLE

複数の並行に動作するトランザクションそれぞれの結果が、いかなる場合でも、それらのトランザクションを時間的重なりなく逐次実行した場合と同じ結果となる。

同時並行実行した結果が逐次実行した結果と同じになるわけが無いので、すなわちこれは、「複数並行に動作しません」ということを指している。 つまり、実行中トランザクションが終わるまで次のトランザクションは処理しないということである。

何かを実行している時は次の実行が必ず待ちに入るということで、データは厳密に保たれるが、複数実行できないのでパフォーマンスは落ちる。 現代の DB は十分高速なので、これでいいような気もするんだが・・・

メリットとしては、データの整合性がタイミングを考えずに保たれるので、安全で使用する側は何も考えなくてよい。

REPEATABLE READ

名前の通り、SELECT に再現性があるということである。 このトランザクションレベルは、トランザクション開始時の状態でその後の他のトランザクションの影響を受けずに進行できるというモノである。

定義上はこうなのであるが、実装によってはこれが不完全になっているモノもあるようだ。

データの読み出しに関しては想定内で動くのだが、更新に関しては外部状況が見れないため意図しない動作になる可能性がある。 後勝ちを採用するとかそういうルールがあるなら問題なく動作する。

アプリ側設計との相性も良いので考えることは少なくてよい。

READ COMMITTED

名前の通り、コミットされたモノは読むということである。 トランザクションの途中であっても、他のトランザクションがコミットさせたモノは反映される。

このため、1回目と2回目のクエリ結果のレコードの内容が変わったり、結果が増減してしまったりする。

実行中でも外部の変更がどんどん反映されてしまうので、処理の最初と最後で前提が変わってくることに注意が必要である。 逆に言うと処理時の最新状態が常に取れるので短い一発ものでは特に問題にならない。

大体アプリではレコードの所有者というのは決まっていてそこを横断して何かするというのは少ないので REPEATABLE READ レベルぐらいのことを考えておけばいいだろう。

READ UNCOMMITTED

コミット前のデータも貪欲に読みに行くというレベル。

ロールバックするかもしれないというデータすら読みに行くということで、実行結果を使い捨てる、最新のみが意味があり、過程に少々間違った値があっても問題無いみたいな状況では選ぶことも許されるだろう。

db/sql/transaction_isolation_level.txt · 最終更新: 2018-09-04 15:55 by ore