詳細検索

隔離レベルについて知っておくべきことと、読書の不整合について

アバター
著者: Chen Ziyu

隔離レベルについて知っておくべきことと、読書の不整合について
Englishから翻訳 • 原文を読む

現実と同様に、コンピュータサイエンスの世界にもトレードオフが満ちています。リレーショナルデータベースも例外ではありません。リレーショナルデータベースとやり取りする際、データの一貫性とトランザクションの並行性というジレンマに直面します。前者はデータの信頼性を保証し、後者はリレーショナルデータベースが迅速に取引を行えるようにします。どちらもリレーショナルデータベースの望ましい特性ですが、同時に最大限に達成することはできません。本日は、アイソレーションレベルがこのジレンマに関する意思決定の構造化にどのように役立つかについて説明します。

矛盾を読んで

アイソレーションレベルに入る前に、まずリレーショナルデータベースでよく見られる3つの読み取り不整合性、すなわちダーティリード、非再現リード、ファントムリードを紹介します。これらは同時トランザクションによって引き起こされるデータ不整合です。アイソレーションレベルを理解する上で非常に重要です。なぜなら、アイソレーションレベルに存在するかどうかがデータの一貫性の度合いを決定するからです。

ダーティーリード

ダーティリードとは本質的にコミットされていないデータの読み取りです。これは、トランザクションが他のトランザクションによって修正されたものの、まだコミットされていないデータを読み取るときに発生します。

例を挙げます:T1とT2という2つの取引があるとします。両者は「BankAccount」と呼ばれる同じテーブルとやり取りします。このテーブルには次の行が含まれています。

table1

 

T1はBankAccountテーブルの上記の行を読み取り、T2はそれを修正します。

「''SQL -- T1のSQL文: 銀行口座から残高を選択し、account_number = 88;


「''SQL
-- T2のSQL文:
更新 銀行口座セット残高 = 800 ここで account_number = 88;

これまでのところ、全体のプロセスは無害なデータベース操作の連続のように聞こえます。しかし問題は、T1がその行を読み込むと、T2はすでに修正済みでコミットしていないため、T1が汚れたデータを読み取ってしまうことです。もしT1の汚れデータをさらに操作に使うと、データベースがT2による修正をロールバックする際に、さらに深刻な問題を引き起こす可能性があります。

繰り返し読めない

非再現性リードは、トランザクション内の同じ行の2回の読み取りが異なる結果を得た場合に発生します。その理由は、別のコミット済みトランザクションが、最初のトランザクションの2回目のリードの後、そして2回目のリードの前にその行を変更したためです。

例を挙げます:2つのトランザクションがあるとします:T1とT2。両者は「Book」と呼ばれる同じテーブルとやり取りします。このテーブルには次の行が含まれています。

table2

 

T1は上記の行をBookテーブルの2回読み、T2はそれを修正します。

「''SQL -- T1のSQL文: 本から価格を選択し ID = 1;本から価格を選択し id = 1;


「''SQL
-- T2のSQL文:
更新 ブックセット価格 = 20 ここで id = 1;

T1の最初の読み取りは『グレート・ギャツビー』の元の価格(15)を正常に取得します。その後、T2は行を更新し、T1の2回目の読み取りが始まる前に価格を変更します。最終的に、T1の2回目の読み取りは最新の価格(20)を取得し、T1は同じ行の2つの読み取り間で不整合が生じます。

ファントムリード

非再現リードと同様に、ファントムリードも同じトランザクション内での読み取り不整合の一種です。これは、同じトランザクション内で2つの同一のリードが異なる行数を返すときに発生します。その理由は、別のコミット済みトランザクションが、最初のトランザクションの後および2回目のリードの前にいくつかの行を挿入または削除したためです。

例を挙げます:2つのトランザクションがあるとします:T1とT2。両者は「Book」と呼ばれる同じテーブルとやり取りします。このテーブルには次の行が含まれています。

table3

 

T1はBookテーブルのすべての行を2回読み込み、T2はBookテーブルに新しい行を挿入します。

「''SQL -- T1のSQL文: 本から選択;本から選択;


「''SQL
-- T2のSQL文:
本に挿入(ID、タイトル、価格) 価値(2、『高慢と偏見』、20)

T1の最初のリードは、本のテーブルで唯一の行(『グレート・ギャツビー』)を取り戻します。その後、T2はT1の2回目のリードが始まる前に、新しい行(『高慢と偏見』)を本のテーブルに挿入します。最終的に、T1の2回目のリードの結果は2行(『グレート・ギャツビー』と『高慢と偏見』)で構成され、T2が挿入した新しい行も含まれます。

隔離レベル

Isolation Levels

次に、SQLトランザクションの4つの分離レベルについて詳しく見ていきます。最も低い分離レベルから始め、残りを昇順に検討します。

未コミットメントで読む

Read Uncommitdは最も低い隔離レベルです。また、トランザクションの並行性が最も高いレベルに対応し、トランザクションが同時にデータベースにアクセスし改変することに制限はありません。前述のリード不整合(ダーティリード、繰り返し不可能なリード、ファントムリード)はすべて起こり得ます。

コミットドを読む

Read Convodedは2番目に低い分離レベルです。トランザクションがコミットされていないデータを読み取らない限り、並行トランザクションを可能にします。この制限により、Read Concommittedは並行性を犠牲にしてダーティリードの可能性を排除します。それでも、繰り返しできないリードやファントムリードが発生する可能性があります。

繰り返し読む

Repeatable Readは2番目に高い隔離レベルです。Read Committedによる制限に加え、Repeatable Readは同じトランザクション内で同じ行の2回の読み取りが異なる結果になることを禁止します。この制限は、トランザクション内の各文が読み取ったすべてのデータに共有ロックを適用することで実現しています。データベースは対応するトランザクションが完了するまで共有ロックを解放しません。その結果、他のトランザクションはロックされたデータに変更を加えることができません。この追加の制限により、トランザクションの同時実行レベルはさらに低下します。この制限により、Repeatable Readは再現不能な読み取りを不可能にしています。しかし、Repeatable Readは依然としてファントム読み取りのリスクに直面しています。

シリアル化可能

Serializableは最も高い分離レベルです。その名の通り、トランザクションが同時に発生する結果がシリアル実行時と同じ場合のみ許可されます。前述の2つの分離レベルによる制限に加え、同じトランザクション内で同じ2つのリードが異なる行数を返すことも禁止しています。この制限は、トランザクション内のすべての文の検索条件に一致するデータ範囲にレンジロックを設置することで実現しています。データベースは対応するトランザクションが完了する前にすべてのレンジロックを保持します。この制限によりトランザクションの同時進行度は最低に低下しますが、Serializableは最高レベルのデータ一貫性を達成するのに役立ちます。3つの読み取り不整合性(ダーティリード、非再現リード、ファントムリード)はいずれも問題ありません。

どの隔離レベルを選ぶべきかのヒント

4つの分離レベルを説明したところで、「では、リレーショナルデータベースのどの分離レベルを選ぶべきか?」と疑問に思う方もいるかもしれません。この質問は本質的に、データの一貫性のためにどれだけの同時実行を犠牲にするかに帰着します。

未コミットメントで読む

経験則としては、Read Uncommitdは避けるべきです。なぜなら、ダーティリードが最も望ましくないデータ不整合のタイプだからです。唯一の例外は、パフォーマンスがデータの整合性よりもはるかに重要になる場合です。

コミットドを読む

Read Committedはほとんどのデータベースにおけるデフォルトの分離レベルです。これは並行性と一貫性のバランスを良くします。どの分離を選ぶべきか迷ったら、まずRead Committedを試してみるのも安全です。

繰り返し読む

リピーダブルリードは、並行性を犠牲にして優れたデータの一貫性を提供します。この隔離レベルを悩ませる唯一のリード不整合はファントムリードです。システムの性能よりもデータの一貫性を重視するなら、リピーダブルリードを選ぶべきです。

シリアル化可能

Serializableは最も高いデータの一貫性を誇ります。その代わり、トランザクションの同時進行度が最も低く、パフォーマンスも最悪です。Serializableは、データの不整合性にゼロトレランスポリシーがある場合に適切な選択肢ですが、システムのパフォーマンスはそれに伴い低下することを忘れないでください。

このブログでは、3種類のリード不整合(ダーティリード、非再現可能リード、ファントムリード)と4つのアイソレーションレベル(Read Uncommitted、Read Committed、Repeatable Read、Serializable)について取り上げました。各アイソレーションレベルは、一部の読まれた不整合を許容し、他を禁止します。これらのアイソレーションレベルの選択は、本質的に並行性と一貫性のトレードオフです。この記事があなたのお役に立てば幸いです。

Related Articles