【のんりぴーたぶるりーど】

ノンリピータブルリード とは?

最終更新:
💡 さっき読んだ値が変わってる!もう一度読んでも同じとは限らない

同じトランザクションで同じ行を読み直したとき、別のトランザクションが変更をコミットしたため、値が変わったり行がなくなったりする現象。ファジーリードとも呼ばれる。

📌 このページのポイント
在庫100個 → 別の取引の確定 → 50個 時間 A SELECT 100個 SELECT 50個 B UPDATE 50個に変更 COMMIT Aの同じ取引中に、読み直した値が変わる Bがコミットした変更を、2回目に読む
在庫の同じ行を読む架空の例。AとBは別のトランザクションで、横方向に時間が進む。Bの更新とコミットは、Aの2つのSELECTの間にある。Read Committedで起こりうる読み取りを示し、50個が誤った値であるという意味ではない。
ひよこ ひよこ
ノンリピータブルリードって、何が繰り返せないの?
ペンギン先生 ペンギン先生
同じトランザクションで、同じ行を読み直しても結果が同じとは限らない現象だよ。たとえば在庫を100個と読んだ後、別のトランザクションが50個に更新してコミットすると、2回目には50個と読むことがあるんだ。
ひよこ ひよこ
Read Committedでも起きるの?
ペンギン先生 ペンギン先生
起きることがあるよ。たとえばPostgreSQLのRead Committedでは、文ごとに、その文の開始時点でコミット済みのデータを読む。2つのSELECTの間に別の取引がコミットすると、結果が変わりうるんだ。
ひよこ ひよこ
ダーティリードとは何が違うの?
ペンギン先生 ペンギン先生
ダーティリードは、別のトランザクションの未コミットの変更を読んでしまうことだよ。こちらは、既に読んだ行を読み直したとき、他の取引がコミットした変更が見えるという違いがあるんだ。
ひよこ ひよこ
防ぐにはどうすればいいの?
ペンギン先生 ペンギン先生
SQL標準ではRepeatable Read以上で防ぐよ。PostgreSQLのRepeatable Readは、最初のトランザクション制御以外の文の開始時点のスナップショットを使う。後から他の取引がコミットした変更は見えないけれど、自分の更新は見える。DBによって、ロックなど実現の仕組みは異なるんだ。
ひよこ ひよこ
ファントムリードは、行の数が変わること?
ペンギン先生 ペンギン先生
数だけではなく、同じ検索条件に一致する行の集合が変わる現象だよ。こちらは既に読んだ行の値の変更や削除に注目する。どちらもUPDATEやDELETEが関係しうるので、SQLの種類だけで分類しないんだ。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「ノンリピータブルリード」って出てきたら「同じ取引中に行を読み直したら、他の取引の変更で結果が変わった現象」と思えばだいたいOK!
📖 おまけ:英語の意味
「Non-Repeatable Read」 = 繰り返し不可能な読み取り
💬 repeatable(繰り返し可能)にnon(否定)がついて、「もう一度読んでも同じ結果にならない」という意味だよ

参考資料

← 用語集にもどる