トランザクション分離レベルとテーブルのロックの関係


105

私は4レベルの分離について読みました:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

各トランザクションの分離がテーブルに対して行うロックを理解たい

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

以下のトランザクション分離で発生する可能性があります3つの現象です
ダーティー読み取りロックなし-
反復不能読み取り -ノーダーティリード、コミットされたデータのロックとして
ファントム読む - (選択クエリを使用して選択される)SQLのブロックのロックが

これらの分離レベルをどこで定義するのかを理解したい:jdbc / hibernateレベルまたはDBでも

PS:私はoracleの分離レベルのリンクを通過しましたが、それらは不格好に見え、データベース固有について話します


3
これはデータベースに完全に依存しています。データベースによって、分離レベルに異なるアルゴリズムが使用される場合があります。MVCCを使用するもの(選択クエリでロックなし)もあれば、厳密な2フェーズロック(共有および排他ロック)を使用するものもあります。
brb tea 2015

回答:


157

各トランザクションの分離がテーブルに対して行うロックを理解たい

たとえば、3つの同時プロセスA、B、Cがあるとします。Aはトランザクションを開始し、データを書き込み、(結果に応じて)コミット/ロールバックします。Bは、SELECTステートメントを実行してデータを読み取るだけです。Cはデータを読み取り、更新します。これらすべてのプロセスは、同じテーブルTで機能します。

  • READ UNCOMMITTED-テーブルはロックされていません。書き込み中にテーブルのデータを読み取ることができます。これは、Aがデータを(コミットされていない)書き込み、Bがこのコミットされていないデータを読み取って(任意の目的で)使用できることを意味します。Aがロールバックを実行しても、Bはまだデータを読み取って使用しています。物理的に関連していないテーブルにデータホールが生じる可能性があるため、これはデータを操作する最も高速ですが最も安全ではない方法です(はい、2つのテーブルは論理的には存在しますが、実際のアプリでは物理的に関連していません= \)。
  • コミット読み取りコミットされたデータをロックします。コミットのみされたデータを読み取ることができます。これは、Aがコミットを実行するまで、Aはデータを書き込み、BはAが保存したデータを読み取ることができないことを意味します。ここでの問題は、CがBで読み取られて使用されたデータを更新できることであり、Bクライアントは更新されたデータを持っていません。
  • REPEATABLE READ -SQLのブロックをロックします(選択クエリを使用して選択されます)。これは、Bがある条件でデータを読み取ることを意味します。つまりWHERE aField > 10 AND aField < 20、Aはデータを挿入します。aField値が10から20の間の、次にBがデータを再度読み取って別の結果を取得します。
  • SERIALIZABLE-テーブル全体(選択クエリが実行される)をロックします。つまり、Bはデータを読み取り、他のトランザクションはテーブル上のデータ変更できません。これは、データを操作するための最も安全ですが最も遅い方法です。また、単純な読み取り操作でテーブルがロックされるため、これは本番環境で重大な問題を引き起こす可能性があります。Tテーブルが請求書テーブルであり、ユーザーXがその日の請求書を知り、ユーザーYが新しい請求書を作成したいとします。 Xが請求書の読み取りを実行している間、Yは新しい請求書を追加することはできません(そして、それがお金の場合、人々は特にボスを怒らせます)。

これらの分離レベルをどこで定義するかを理解したい:JDBC /ハイバネートレベルまたはDBでも

JDBCを使用する場合は、を使用して定義しConnection#setTransactionIsolationます。

Hibernateの使用:

<property name="hibernate.connection.isolation">2</property>

どこ

  • 1:コミットされていない読み取り
  • 2:コミット読み取り
  • 4:反復可能読み取り
  • 8:シリアライズ可能

Hibernate設定はここから取得されます(申し訳ありませんが、スペイン語です)。

ところで、RDBMSにも分離レベルを設定できます。

そしてどんどん...


docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm Oracleに追加するだけ:トランザクションの最初に次のステートメントのいずれかを使用して、トランザクションの分離レベルを設定できます。SET TRANSACTION ISOLATIONレベルREAD COMMITTED; トランザクションの分離レベルをシリアライズ可能に設定します。トランザクションを読み取り専用に設定します。
学習者、2014

2
さらに、SET TRANSACTIONステートメントで各トランザクションを開始するネットワークと処理のコストを節約するために、ALTER SESSIONステートメントを使用して、後続のすべてのトランザクションのトランザクション分離レベルを設定できます。ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE; ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
学習者

12
REPEATABLE READについて-私はそれを示すより良い例を以下に示します。Bはトランザクションを開始し、SQLのブロックでデータを読み取ります。Aはそのデータを更新しようとしますが、ロックのために待機します。これで、Bが同じトランザクションでそのデータを再度読み取るときに、ロックされているため、同じデータを読み取ることが保証されます。私が間違っていたら訂正してください。
BornToCode 2015

1
@LuiggiMendoza一般的な概念として、分離レベルは、ダーティリード繰り返し不可の読み取り、およびファントム行です。ロック(S2PL)またはMVCCは、さまざまなベンダー向けの実装です。
brb tea 2015

4
@LuiggiMendoza-私は正確ではありませんでした。これは次のようになるはずです-Bが読み取ったデータは変更されませんが、結果としてBが行った選択により多くの行が返される可能性があります。これ、Aが解放するまで、Bがすでに読み込んだ行をAが変更できないためです。ただし、A はwhere条件を修飾する新しい行を挿入できます(したがって、次にAが選択を実行するときは、より多くの行を持つ別の結果が得られます-ファントムリード)。
BornToCode

9

brb teaが言うように、データベースの実装とそれらが使用するアルゴリズム(MVCCまたは2フェーズロック)によって異なります。

CUBRID(オープンソースRDBMS)、この2つのアルゴリズムの考え方を説明しています。

  • 2フェーズロック(2PL)

1つ目は、T2トランザクションがAレコードを変更しようとしたときに、T1トランザクションがすでにAレコードを変更したことを認識しており、T2トランザクションがT1トランザクションがコミットされるかロールされるかを認識できないため、T1トランザクションが完了するまで待機します。バック。この方法は2フェーズロック(2PL)と呼ばれます。

  • マルチバージョン同時実行制御(MVCC)

もう1つは、T1およびT2トラ​​ンザクションのそれぞれが独自のバージョンを変更できるようにすることです。T1トランザクションがAレコードを1から2に変更した場合でも、T1トランザクションは元の値を1のままにし、AレコードのT1トランザクションバージョンが2であると書き込みます。次に、次のT2トランザクションはAレコードを変更します1から3、2から4ではなく、AレコードのT2トランザクションバージョンが3であると書き込みます。

T1トランザクションがロールバックされるとき、T1トランザクションバージョン2がAレコードに適用されていなくても問題ありません。その後、T2トランザクションがコミットされると、T2トランザクションバージョン3がAレコードに適用されます。T2トランザクションの前にT1トランザクションがコミットされると、T2トランザクションのコミット時にAレコードが2に変更され、次に3に変更されます。最終的なデータベースのステータスは、他のトランザクションに影響を与えることなく、各トランザクションを個別に実行するステータスと同じです。したがって、ACIDプロパティを満たします。この方法は、マルチバージョン同時実行制御(MVCC)と呼ばれます。

MVCCは、メモリ内のオーバーヘッドの増加(同じデータの異なるバージョンを維持する必要があるため)と計算(REPETEABLE_READレベルでは更新を失うことができないため、Hiberateなどのデータのバージョンをチェックする必要がある)を犠牲にして、同時変更を許可しますとする Optimistickロック)。

2PL トランザクション分離レベルでは、以下を制御します

  • データの読み取り時にロックが取得されるかどうか、および要求されるロックのタイプ。

  • 読み取りロックが保持される期間。

  • 別のトランザクションによって変更された行を参照する読み取り操作かどうか。

    • 行の排他ロックが解放されるまでブロックします。

    • ステートメントまたはトランザクションの開始時に存在していた行のコミット済みバージョンを取得します。

    • コミットされていないデータ変更を読み取ります。

トランザクション分離レベルを選択しても、データ変更を保護するために取得されるロックには影響しません。トランザクションは、変更するすべてのデータに対して排他ロックを取得し、トランザクションに設定された分離レベルに関係なく、トランザクションが完了するまでそのロックを保持します。読み取り操作の場合、トランザクション分離レベルは主に、他のトランザクションによって行われた変更の影響からの保護レベルを定義します。

分離レベルを低くすると、多くのユーザーが同時にデータにアクセスできるようになりますが、同時実行効果の数は増えます。ようになりますが、ユーザーが遭遇する可能性のあるダーティリードや更新の喪失などます。

SQL Serverでのロックと分離レベルの関係の具体例(READ_COMMITTED_SNAPSHOT = ONを指定したREAD_COMMITEDを除く2PLを使用)

  • READ_UNCOMMITED:他のトランザクションが現在のトランザクションによって読み取られたデータを変更するのを防ぐために、共有ロックを発行しないでください。READ UNCOMMITTEDトランザクションは、現在のトランザクションが変更されたが他のトランザクションによってコミットされていない行を読み取ることを妨げる排他ロックによってもブロックされません。[...]

  • READ_COMMITED:

    • READ_COMMITTED_SNAPSHOTがOFF(デフォルト)に設定されている場合:共有ロックを使用して、現在のトランザクションが読み取り操作を実行している間、他のトランザクションが行を変更しないようにします。共有ロックは、他のトランザクションが完了するまで、他のトランザクションによって変更された行をステートメントが読み取ることもブロックします。[...]次の行が処理される前に行ロックが解放されます。[...]
    • READ_COMMITTED_SNAPSHOTがONに設定されている場合、データベースエンジンは行のバージョン管理を使用して、ステートメントの開始時に存在していたトランザクションのデータのスナップショットを各ステートメントに提示します。ロックは、他のトランザクションによる更新からデータを保護するためには使用されません。
  • REPETEABLE_READ:トランザクション内の各ステートメントによって読み取られたすべてのデータに共有ロックが設定され、トランザクションが完了するまで保持されます。

  • SERIALIZABLE:範囲ロックは、トランザクションで実行される各ステートメントの検索条件に一致するキー値の範囲に配置されます。[...]範囲ロックは、トランザクションが完了するまで保持されます。


5

ロックは常にDBレベルで行われます。

Oracleの公式ドキュメント:-トランザクション中の競合を回避するために、DBMSはロックを使用します。これは、トランザクションがアクセスしているデータへの他のユーザーによるアクセスをブロックするメカニズムです。(各ステートメントがトランザクションである自動コミットモードでは、ロックは1つのステートメントに対してのみ保持されることに注意してください。)ロックが設定された後、トランザクションがコミットまたはロールバックされるまでロックは有効なままです。たとえば、DBMSは、更新がコミットされるまで、テーブルの行をロックできます。このロックの効果は、ユーザーがダーティリード、つまり永続化される前に値を読み取ることを防ぐことです。(コミットされていない更新された値にアクセスすると、その値が以前の値にロールバックされる可能性があるため、ダーティリードと見なされます。後でロールバックされた値を読み取ると、無効な値が読み取られます。 )

ロックの設定方法は、いわゆるトランザクション分離レベルによって決定されます。トランザクション分離レベルは、トランザクションをまったくサポートしないことから、非常に厳密なアクセスルールを適用するトランザクションをサポートすることまでさまざまです。

トランザクション分離レベルの1つの例はTRANSACTION_READ_COMMITTEDであり、コミットされるまで値にアクセスできません。つまり、トランザクション分離レベルがTRANSACTION_READ_COMMITTEDに設定されている場合、DBMSはダーティリードの発生を許可しません。インターフェースConnectionには、JDBCで使用できるトランザクション分離レベルを表す5つの値が含まれています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.