1. ホーム
  2. java

[解決済み] トランザクションの分離レベルとテーブルのロックの関係

2022-08-23 20:47:02

質問

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つの現象は以下の通りです。

ダーティリード - ロックなし

繰り返し不可能な読み取り - コミットされたデータをロックするため、ダーティリードがない

ファントムリード - selectクエリで選択されたSQLのブロックをロックする。

私は理解したい これらの分離レベルは、jdbc/hibernateレベルのみか、DB内でも定義できるのでしょうか?

PS: 私は、以下のリンクに目を通しました。 オラクルにおける分離レベル のリンクも見てみましたが、不器用そうだし、データベース固有の話もありそうです。

どのように解決するのですか?

<ブロッククオート

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

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

  • 未コミットの読み込み - テーブルをロックしていません。テーブルに書き込みをしながら、テーブルのデータを読み込むことができる。つまり、Aが(コミットされていない)データを書き込み、Bはこのコミットされていないデータを読み込んで(どんな目的でも)使用することができる。Aがロールバックを実行しても、Bはそのデータを読んで使用したことになる。これは最も速い方法ですが、物理的に関連していないテーブルのデータホールにつながるため、データを扱うのに最も安全でない方法です(実際のアプリケーションでは、2つのテーブルが論理的に関連しても、物理的に関連しないことがあります)。
  • READ COMMITTED - はコミットされたデータをロックします。コミットされただけのデータを読むことができる。つまり、Aがデータを書き込み、BはAがコミットを実行するまでAが保存したデータを読めません。ここで問題なのは、CがBに読み込まれ使用されたデータを更新することができ、Bのクライアントは更新されたデータを持つことができなくなることです。
  • 繰り返し読み出し - SQLのブロック(selectクエリで選択されたもの)をロックします。これは、Bがある条件下でデータを読み込むことを意味します。 WHERE aField > 10 AND aField < 20 Aがデータを挿入する場合 aField の値が 10 と 20 の間にあるデータを挿入し、B はそのデータを再度読み込んで異なる結果を得ます。
  • SERIALIZABLE - はフルテーブル(Selectクエリが発行されるテーブル)をロックします。つまり、Bはデータを読み込んで 他のトランザクションがデータを変更することはできません。 を変更できないことを意味します。これは最も安全な方法ですが、データを扱うのに最も遅い方法です。また、単純な読み取り操作でロックされるため テーブルを TテーブルがInvoiceテーブルで、ユーザーXがその日のinvoiceを知り、ユーザーYが新しいinvoiceを作成したいと想像してみてください。

理解したい これらの分離レベルを定義する場所:JDBC/hibernateレベルのみ、またはDBでも。

JDBCを使用する場合、以下の方法で定義します。 Connection#setTransactionIsolation .

Hibernateを使用します。

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

ここで

  • 1: コミットされない読み取り
  • 2: コミット済み読み込み
  • 4: 繰り返し読み出し
  • 8: シリアライズ可能

Hibernateの設定は ここで (から取得しています(すみません、スペイン語です)。

ちなみに、RDBMSでもアイソレーションレベルを設定することができます。

といった具合に...