はじめに
今回はSQLserverにおけるトランザクション分離レベルの超入門ということで、以下のような人を想定して書いています。
- SQLはかけるが、トランザクション分離レベルというものは知らない
- トランザクション分離レベルというものがあることはわかるが、何となくで理解している
そのような方が、記事を読んで少しでも分離レベルに興味を持っていただけたらなと思います!
トランザクション
前提としてクエリを使って行う一連の操作をトランザクションという単位で表します。
※UPDATEやDELETEなど意味を持ったクエリの塊をマイグレーションなどと呼んだりもします。
トランザクションを設定しなくてもクエリを実行できますが、一連の操作をCOMMIT(確定)・ROLLBACK(もとに戻す)のどちらかになることを保証するためにもトランザクションは張る必要があります。
そのトランザクションにもいくつか種類があり、それぞれにメリットデメリットがあるので、適切に使用する必要があります。
複数のトランザクションが同時に実行されることで発生する不整合
とても簡単に記載していますが、以下のような問題が発生するケースがあります。
-
Dirty Read
別トランザクションでまだコミットされていないデータを読んでしまう現象 -
Fuzzy Read
トランザクション内で同じデータを2回以上読み取った際にそれぞれが別の結果になってしまう現象 -
Phantom Read
トランザクション中に、別トランザクションによってデータを追加されたり削除されることによって処理結果に不整合が起こってしまう現象
トランザクション分離レベル
大きく分けて以下のレベルが存在します
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SNAPSHOT
- SERIALIZABLE
トランザクション分離レベルと不整合の関係
トランザクション分離レベル | Dirty Read | Fuzzy Read | Phantom Read |
---|---|---|---|
READ UNCOMMITTED | 〇 | 〇 | 〇 |
READ COMMITTED | × | 〇 | 〇 |
REPEATABLE READ | × | × | 〇 |
SERIALIZABLE | × | × | × |
〇が発生、×が発生しません。
SNAPSHOTに関しては、事前準備が必要なこと、temp_dbを使用するため使用領域がかなり多くなってしまうこと、更新系の処理ではむしろ速度が低下することなどから使うケースが少ないので割愛します。
トランザクション分離レベルの設定方法&考え方
使い方は簡単で、このようにトランザクションを張っている状態で1行目のように記述します。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN
SELECT *
FROM Sampl_Table
WHERE user_id = '0001'
ROLLBACK
-- COMMIT
(会社によるかもしれませんが)業務中に使用するトランザクション分離レベルは、READ UNCOMMITTEDかREAD COMMITTEDがほとんどです、それ以外はほとんど使用しないです。
今回は第一歩ということで、READ UNCOMMITTEDとREAD COMMITTEDを使い分けることができる状態になっていただけたいので、簡単な考え方を書いておきます。
-
READ UNCOMMITTED
テーブルなどに一切のロックをかけない設定のため、複雑な条件のSELECTなどで大量のデータを参照して抽出する場合などに有効、データを一旦吐かせておく置くなどはテーブルにロックをかけてしまうと大変なことになるので、READ UNCOMMITTEDを使用する -
READ COMMITTED
ダーティーリードを防ぐ分離レベルであり、最低限のロックを獲得します、そのため上記以外のケース(登録・更新)刑の操作を行うときに有効です。
最後に
もっと厳密に考えるとまだまだ使い分けの基準は存在しますが、これから覚えていこうという方は一旦参照のみならREAD UNCOMMITTED、登録更新があればREAD COMMITTEDと覚えておくだけでもかなり違ってくるので、ぜひ意識してみてください!!