はじめに
こんにちは。アメリカに住みながら、独学でエンジニアを目指しているTairaです。
SQLを学習中ですが、トランザクションの中で発生してしまうダーティーリード、Non_repeatable read(反復不能読み取り), ファントムリードがあります。
本日はその中でファントムリードについて説明していきたいと思います。
ファントムリードとは何か?
トランザクションの分離レベルに関する話題の中で、「ファントムリード(Phantom Read)」という用語を聞いたことがあるでしょうか?この記事では、ファントムリードとは何かを具体例とともにわかりやすく解説していきます。
ファントムリードの意味
ファントムリードとは、同一トランザクション内で同じ検索条件でクエリを複数回実行したときに、前回には存在しなかった"新しい行(ファントム)"が結果に現れる現象のことを指します。
実例
「価格が500円以上の商品一覧」を取得したいとします。
トランザクションA ( あなた )
BEGIN;
SELECT * FROM items WHERE price >= 500;
結果:
id | name | price |
---|---|---|
1 | Book | 800 |
2 | Headphones | 1000 |
トランザクションB ( 別の人 )
INSERT INTO items (id, name, price) VALUES (3, 'Mouse', 700);
COMMIT;
トランザクションAで再度同じクエリを実行
SELECT * FROM items WHERE price >= 500;
結果:
id | name | price |
---|---|---|
1 | Book | 800 |
2 | Headphones | 1000 |
3 | Mouse | 700 |
なぜ起こるのか
REPEATABLE READ や READ COMMITTED といった分離レベルは
- "行の内容の変更"は防げても
- "条件に合致する新しい行の追加"は防げない
ファントムリードを防ぐには
SERIALIZABLE という最高レベルの分離性を使用することで防ぐことができます。
トランザクション副作用のまとめ
用語 | 内容 |
---|---|
ダーティーリード | 他トランザクションの 未コミットデータ を読む |
ノンリピータブルリード | 同じ行を再度読んだときに 内容が変わっている |
ファントムリード | 同じ条件の検索で 新しい行が返ってくる |
まとめ
- ファントムリードは、同じSQLで読み取る行の数が変わる
- REPEATABLE READでも防げず、SERIALIZABLEで防げる
- 他のリード問題と違いを理解しておくとデータ事故を防ぐことができます