はじめに
こんにちは。アメリカに住みながら、独学でエンジニアを目指しているTairaです。
SQLを学習中ですが、トランザクションの中で発生してしまうダーティーリード、Non_repeatable read, ファントムリードがあります。
本日はその中でもダーティーリードについて説明していきたいと思います。
ダーティーリードとは
SQLのトランザクション管理における「ダーティーリード(Dirty Read)」とは、他のトランザクションがまだコミット(確定)していないデータの変更を読み取ってしまう現象を指します。
具体的な例(口座振込のケース)
以下のように、2つのトランザクションを想定してみましょう。
トランザクションA(送金処理をしている途中)
BEGIN;
UPDATE accounts SET balance = balance - 10000 WHERE id = 1; -- 送金元口座から1万円引く
-- ここでまだCOMMITを実行していない(未確定の状態)
トランザクションB(同時に残高をチェックする処理)
SELECT balance FROM accounts WHERE id = 1;
-- トランザクションAの未コミットの変更を読み取ってしまう
このケースで、トランザクションBが未確定の変更(送金処理が完了していないのに引かれた状態の残高)を読んでしまう状態が「ダーティーリード」です。
ダーティーリードが問題となる理由
- トランザクションAが途中でエラーなどの理由でROLLBACKされた場合、トランザクションBが読み取ったデータは実際には存在しない(無効な)データとなります。
- このように不確定な情報を元に、誤った判断や処理を進める可能性があります。
ダーティーリードが起こる分離レベル
SQLにはトランザクションの分離レベル(Isolation Level)があり、分離レベルによってダーティーリードの発生の有無が決まります。
分離レベル(Isolation Level) | ダーティーリードの発生 |
---|---|
READ UNCOMMITTED | 発生する ❌ |
READ COMMITTED | 発生しない ✅ |
REPEATABLE READ | 発生しない ✅ |
SERIALIZABLE | 発生しない ✅ |
つまり、ダーティーリードが許されるのは分離レベルがREAD UNCOMMITTEDの場合だけです。
なぜREAD UNCOMMITTEDでは発生するのか?
READ UNCOMMITTEDの分離レベルでは、読み取り時に共有ロックを取得しないので、他のトランザクションが未コミットのデータを読むことが許可されています。
まとめ
ダーティーリードはデータベース処理において信頼性を損なうリスクがあるため、基本的にはREAD COMMITTED以上の分離レベルを設定することが推奨されています。特に口座振込など重要な処理では、誤ったデータの読み取りを防ぐためにも高い分離レベルを用いることが重要です。