データベーススペシャリスト 2017年 午前2 問17
問題文
図は、ある探索条件を使って数学模試の平均点を算出している間、当該探索条件に合致するA君の結果を“数学模試成績”表に登録したときの様子を示している。平均点を求めるトランザクションT1と、登録作業のトランザクションT2が①~⑥の順序で処理された結果、合計点算出時の受験者数と平均点算出時の受験者数が異なり、正しい平均点を得ることができなかった。このとき発生した事象はどれか。ここで、トランザクションの隔離性水準はREAD UNCOMMITTEDであったとする。

選択肢
ア:アンリピータブルリード
イ:シーケンシャルリード
ウ:ダーティリード
エ:ファントムリード(正解)
🔒 解説は解答すると表示されます
ファントムリード【午前2解説】
正解の理由
正答は エ です。設問の状況では、トランザクションT1が最初に該当行の合計点Xを読み取り、その後T2が新しい行(A君の成績)を挿入してコミットし、T1が後で受験者数Yを読み取っています。T1の同一「探索条件」に対する複数回の読取りで結果に新しい行が現れ、最初の読取り結果と後の読取り結果で「集合(行の集合)」が変化しているため、これはファントムリード(phantom read)に該当します。したがって選択肢の中では エ が該当します。
平均は で計算されますが、 に新規行が含まれず に含まれるため、誤った平均が算出されます。
解法ステップ
- 各操作の時系列を整理する:T1 の第1読取り → T2 の挿入・コミット → T1 の第2読取り。
- それぞれの読取りが「行集合(どの行が該当するか)」に対して行われているかを確認する。ここでは集計(SUM/COUNT)なので「該当行の集合の変化」が重要。
- もし同一トランザクション内で同じ探索条件の複数回読取りによって行集合や取得行が増減(新しい行が出現)していれば、ファントムリードと判定する。
- よって正答は エ(ファントムリード)。
選択肢別の誤答解説
-
ア: アンリピータブルリード(non‑repeatable read)
既存の単一行をT1が読み、その後別トランザクションがその行の値を更新してT1が再読取すると値が変わる現象を指します。本問題は「新しい行の出現」による集合の変化であり、単一既存行の値が変わるケースではないため該当しません。 -
イ: シーケンシャルリード
これは標準的なトランザクション異常の名称ではなく、本問題の文脈では該当しません(選択肢として誤り)。 -
ウ: ダーティリード(dirty read)
ダーティリードは他トランザクションがまだコミットしていない変更を読み取る現象です。本設問ではT2はコミットしている(T2の挿入→コミット→その後T1が再読取)ため、T1はコミット済みの状態を読み取っており、ダーティリードではありません。 -
エ: ファントムリード(phantom read)
同一トランザクション内の同一探索条件での複数回の読取りで、行集合が増減する現象。問題の事象に一致します。
よくある誤解
-
「REPEATABLE READやREAD COMMITTEDでファントムは起きない」という誤解
SQL標準上、ファントムを確実に防げるのは SERIALIZABLE のみです。DBMS の実装によっては REPEATABLE READ でもファントムを防げる場合がありますが、標準としては保証されません。 -
ダーティリードとファントムの混同
「データが変わった」=ダーティリードと短絡的に判断する人がいます。ダーティリードは「未コミットの変更を読むこと」、ファントムは「行集合の変化(新規挿入や削除が見えること)」です。時系列とコミット有無を必ず確認してください。
補足コラム
-
SQL標準における主要な分離レベルと防止される現象(簡易まとめ)
- READ UNCOMMITTED: ほとんどの異常を防がない(ダーティリードを許す)
- READ COMMITTED: ダーティリードを防ぐ(ただし繰り返し読取で結果が変わる可能性あり)
- REPEATABLE READ: ダーティリードとアンリピータブルリードを防ぐ(ただしファントムは標準上は防がれない)
- SERIALIZABLE: ファントムを含む主要な異常を防ぐ(最も強い整合性を提供)
実際のDBMSでは実装(ロック方法やMVCCの設計)により振る舞いが異なるため、問題や試験では「SQL標準上の定義」を踏まえて判断することが重要です。
-
試験的な対策の実務例
集計処理で一貫性のある結果を得たい場合は、該当処理を SERIALIZABLE で実行するか、トランザクション開始時に一貫したスナップショット(Snapshot Isolation)を取得する、あるいは該当テーブルに対して適切な共有ロックを取得する等の方法があります。
FAQ
Q1: T1がT2の未コミットデータを先に読んでいたら何になる?
A1: もしT1がT2の未コミットの挿入を読んでいたらそれはダーティリードになります(READ UNCOMMITTED では発生し得る)。
A1: もしT1がT2の未コミットの挿入を読んでいたらそれはダーティリードになります(READ UNCOMMITTED では発生し得る)。
Q2: このケースでREPEATABLE READにすれば確実に防げるか?
A2: SQL標準ではREPEATABLE READでファントムは保証されません。実装によっては回避できる場合もありますが、確実に防ぐには SERIALIZABLE を用いるのが標準的な方法です。
A2: SQL標準ではREPEATABLE READでファントムは保証されません。実装によっては回避できる場合もありますが、確実に防ぐには SERIALIZABLE を用いるのが標準的な方法です。
Q3: 平均値を確実に正しく出すにはどうすればよいか?
A3: 同一トランザクション内で読み取りのスナップショットを固定する(例: SERIALIZABLE、あるいはMVCCでの一貫したスナップショット)か、読み取りと書き込みが競合しないようロック運用(集計対象に対する排他制御)を行います。
A3: 同一トランザクション内で読み取りのスナップショットを固定する(例: SERIALIZABLE、あるいはMVCCでの一貫したスナップショット)か、読み取りと書き込みが競合しないようロック運用(集計対象に対する排他制御)を行います。
関連キーワード: トランザクション, 分離レベル, ファントムリード, ダーティリード, アンリピータブルリード, READ UNCOMMITTED, SERIALIZABLE, 一貫性, MVCC

\ せっかくなら /
データベーススペシャリストを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

