SQL の分離レベルは、データベース内でトランザクションが互いに分離される程度を指します。トランザクション A があるデータを変更した後、その時点でトランザクション B がデータを読み取るとどうなるでしょうか? これは、データベースの分離レベル設定によって異なります。
一般的に使用されるトランザクション分離レベルのタイプには次のものがあります。
- READ UNCOMMITTED (コミットされていない読み取り): この分離レベルでは、コミットされていないトランザクションによって行われた変更を読み取ることができますが、コミットされていないトランザクションはコミットされたトランザクションによって行われた変更を読み取ることはできません。したがって、この分離レベルでは、ダーティ読み取りや反復不能読み取りの問題が発生する可能性があります。
- READ COMMITTED (コミットされた読み取り): この分離レベルでは、コミットされたトランザクションによって行われた変更の読み取りのみが許可されますが、コミットされていないトランザクションによって行われた変更は許可されません。したがって、この分離レベルではダーティ リードの問題を回避できますが、反復不可能な読み取りの問題が発生する可能性があります。
- REPEATABLE READ: この分離レベルでは、コミットされたトランザクションによって行われた変更を読み取ることができ、同じトランザクションが同じデータを複数回読み取る場合でも、結果の一貫性が維持されます。したがって、この分離レベルでは反復不可能な読み取りの問題を回避できますが、ファントム読み取りが発生する可能性があります。
- SERIALIZABLE: この分離レベルは、シリアルに実行されるすべてのトランザクションと同等であり、すべての同時実行の問題を回避できますが、パフォーマンスに重大な影響を与えます。
まず、いくつかの用語を理解する必要があります。
1. ダーティ リード: トランザクション ウィンドウでは、データ変更がコミットされなくなる前に、別のトランザクションがメモリ内のデータ ページの変更を確認できます。つまり、他者が送信していないデータ情報をトランザクションウィンドウで読み取ることができます。
たとえば、トランザクション A はデータを変更しましたが、まだ送信していません。
トランザクション B はこの変更された値を読み取ります
このとき、トランザクション A が突然ロールバックしました。
トランザクション B は存在しないデータを読み取ることと同じです
2. 反復不可能な読み取り: 15 年間の期間内で、最初の一意のデータが、トランザクション終了前の任意の時点で読み取られた同じデータ バッチと一致しない状況を指します。
たとえば、トランザクション A は 1 つのデータを複数回読み取ります。
トランザクション B がその中のデータを更新し、コミットしました
トランザクション A を複数回読み取った結果は異なります。
3. ファントム読み取り: トランザクションが独立して実行されない場合、トランザクションはテーブル内のデータを変更します。この変更にはテーブル内のすべてのデータ行が含まれます。たとえば、最初のトランザクションでテーブル内のすべての行を読み取り、次に 2 番目のトランザクションで新しいデータ行を挿入すると、最初のトランザクションで読み取られたデータ行が不完全になり、ファントム読み取りが発生します。
2 回の選択で取得される数は異なります。たとえば、最初の選択では 10 行が取得され、2 回目の選択では 20 行が取得されます。
たとえば、トランザクション A が初めてデータを選択すると、5 行のデータが取得されます。
トランザクション B はこの時点で 5 行を挿入しました
Aselect データの 2 回目のトランザクションでは 10 行のデータが取得されましたが、当初の意図が 6 行目から挿入を開始することだった場合、この時点で競合が発生します。
分離レベル | ダーティリード | 反復不可能な読み取り | 幻の読書 |
コミットされていない読み取り | 起こる | 起こる | 起こる |
送信済みを読む | 起こらない | 起こる | 起こる |
反復可能な読み取り | 起こらない | 起こらない | ネクストキーロックで解決 |
シリアル読み取り | 起こらない | 起こらない | 起こらない |
コミットされていない読み取りの場合、トランザクション内で変更されたデータはコミットされていませんが、他のトランザクションからは参照されます。
ダーティ リードは避けられず、反復不可能なリードやファントム リードも同様です。
読み取りコミットの場合、トランザクションで変更されたデータは、送信後に他のトランザクションでのみ表示されます。
ダーティ リードは完全に回避できますが、繰り返し読み取り中にコミットされてしまうと問題が発生するため、ノンリピータブル リードやファントム リードは避けることができません。
反復可能な読み取りの場合、ダーティ読み取りおよび反復不可能な読み取りを回避できます。
読み取りビューは、反復可能な読み取り分離レベルの下で MySQL によって作成されたビューであり、トランザクションごとに一貫したデータ スナップショットを提供します。読み取りビューには、トランザクションの開始時にアクティブだったすべてのトランザクション ID が記録されます。Read View を通じて、トランザクションは他のトランザクションによって変更される前にデータ行を読み取ることができるため、反復可能な読み取りと mvcc の提供が実現されます。
シリアル化の場合、すべてのトランザクションがシリアルに実行されるため、同時実行の問題はすべて回避できますが、効率は非常に低くなります。