汚い読み、繰り返してはいけない読み、幻読み
6126 ワード
ロックは、他のトランザクションが指定したリソースにアクセスすることを防止する手段です.ロックは同時制御を実現する主な方法であり、複数のユーザがデータの不一致現象を起こさずに同じデータベース内のデータを同時に操作できる重要な保障である.一般に、ロックは、汚れた読み取り、繰り返し不可能な読み取り、幻覚的な読み取りを防止することができる.
トランザクション同時発生の問題:ダーティリード:あるトランザクションが別のトランザクションにコミットされていないデータトランザクションに読み込まれた1:データの更新----------トランザクション2:トランザクション1更新のレコードトランザクションを読み込む1:コミットのためにcommitを呼び出す***トランザクション2がのデータは、ダーティリードと呼ばれるデータベースメモリに保存されているデータです.***読み込まれたデータはダーティデータとして詳しく説明されています.ダーティリードとは、1つのトランザクションがデータにアクセスし、データが変更されていて、この変更がデータベースにコミットされていない場合、別のトランザクションもこのデータにアクセスし、このデータを使用します.このデータはまだコミットされていないデータなので、別のトランザクションが読み取ったこのデータは汚いデータであり、汚いデータに基づいた操作は正しくない可能性があります.繰り返し不可:同じトランザクションで同じデータを2回読み込み、内容の異なるトランザクションを取得する1:レコードを問い合わせる-------->トランザクション2:トランザクション1クエリーのレコードを更新する-------->トランザクション2:commitを呼び出してトランザクションを提出する1:前回のレコードを再度問い合わせる***このときトランザクション1は同じ1つのデータは2回クエリーされ、得られる内容は異なり、繰り返し不可幻読と呼ばれます.同じトランザクションで同じ操作で2回読み取り、得られたレコード数が異なるトランザクション1:クエリー・テーブル内のすべてのレコード-------->トランザクション2:レコードを挿入-------->トランザクション2:commitを呼び出してコミットトランザクション1:テーブル内のすべてのレコードを再クエリー***このとき、トランザクション1が2回クエリーされたレコードは異なり、幻読詳細解釈と呼ばれます.幻読とは、トランザクションが独立して実行されていない場合に発生する現象です.たとえば、最初のトランザクションがテーブル内のデータを変更した場合、テーブル内のすべてのデータ行に関連します.同時に、2番目のトランザクションもこのテーブルのデータを変更します.この変更は、テーブルに新しいデータを挿入することです.すると,後で最初のトランザクションを操作したユーザがテーブルに変更されていないデータ行があることに気づき,まるで幻覚が起こったかのようになる.
次のような独立性レベルの問題を処理します.
トランザクション・アイソレーションの5つのレベル:TRANSACTION_NONEはトランザクションを使用しません. TRANSACTION_READ_UNCOMMITTEDは汚れた読みを許可します. TRANSACTION_READ_COMMITTEDはダーティリードを防止し、最も一般的な独立性レベルであり、ほとんどのデータベースのデフォルトの独立性レベルTRANSACTION_である.REPEATABLE_READは汚れた読み取りと重複しない読み取りを防止することができ、TRANSACTION_SERIALIZABLEはダーティリードを防止し、繰り返し読み取りや幻読みができず、データベースの効率を低下させる
以上の5つのトランザクション独立性レベルは、Connectionインタフェースで定義された静的定数です.
setTransactionIsolation(int level)メソッドを使用して、トランザクションの独立性レベルを設定します.如:con.setTransactionIsolation(Connection.REPEATABLE_READ);
注意:トランザクションの独立性レベルはデータベースによって制限されます.データベースによってサポートされる独立性レベルは必ずしも同じではありません.
1ダーティリード:変更時に排他ロックをかけ、トランザクションがコミットされてから解放され、読み込み時に共有ロックをかけ、読み出しが完了してトランザクション1のデータを読み出す時に共有ロックをかけた後(トランザクション1がデータを読み出す過程で他のトランザクションはデータを修正しない)、データを操作することは一切許されず、読み取りのみが可能となり、その後1更新操作があれば排他ロックに変換され、他の事務は読み書きに参加する権利がなく、汚い読み書きの問題を防ぐことができます.
しかし、トランザクション1がデータを読み出す過程で、他のトランザクションもそのデータを読み取った可能性があり、読み取りが完了すると共有ロックが解放され、トランザクション1がデータを修正し、修正が完了してトランザクションをコミットし、他のトランザクションが再びデータを読み取る際にデータが一致しないことに気づき、重複しない問題が発生するため、重複しない問題を回避することはできない.
2繰り返して読むことはできません:データを読み取る時に共有ロックをプラスして、データを書く時に排他ロックをプラスして、すべて事務が提出してやっとロックを解放します.読み込み時に他のものにこのデータを修正することは許されず、データがトランザクション中に何度読み込まれても、データは一致しており、重複しない読み取り問題を回避している3幻読み問題:範囲ロックRangeS RangeS_を採用しているSモードでは,ロック検索範囲が読み取り専用であるため,幻影読解の問題を回避することができるが,ここでは範囲ロックを記述する文章がある.
異なる独立性レベルを実行すると、さまざまな問題が発生する可能性があります.次に、それらをまとめ、例を挙げて説明します.
幻読み:幻読みは、2つのまったく同じクエリーが実行されると、2回目のクエリーで返される結果セットが最初のクエリーとは異なる場合に発生します.
発生した場合:範囲ロックはありません.
例:
トランザクション1
トランザクション2
回避方法:シーケンス化された独立性モードを実行すると、どの低レベルの独立性でも発生する可能性があります.
繰り返し不可
ロックベースのパラレル制御方法では、selectを実行するときにリードロックを追加しないと、重複しない読み取りの問題が発生します.
マルチバージョンパラレル制御メカニズムでは、コミット競合に遭遇したトランザクションがロールバックされ、解放される必要がある場合、重複しない読み取りの問題が発生します.
トランザクション1
トランザクション2
上記の例では、トランザクション2のコミットに成功し、その変更が表示されます.しかし、トランザクション1は他の値を読み出した.シーケンス化および繰返し可能な独立性レベルでは、データベース管理システムは、トランザクション2によって変更される前の値である古い値を返します.コミットされた読み取りとコミットされていない読み取りの独立性レベルでは、更新された値が返される場合があります.これが「繰り返し読み取り不可」です.
この問題の発生を防止するには、次の2つのポリシーがあります.
1.トランザクション1がコミットまたはロールバックされるまで、トランザクション2の実行を延期します.このポリシーは、ロックを使用するときに適用されます.
2.複数バージョンの並列制御では、トランザクション2を先にコミットできます.トランザクション1は、古いバージョンのデータに引き続き実行されます.トランザクション1が最終的にコミットしようとすると、データベースはトランザクション1、トランザクション2の順序と同じ結果を検証します.もしそうであれば、トランザクション1のコミットは成功しました.そうでない場合、トランザクション1はロールバックされます.
汚読
ダーティリードは、あるトランザクションAが別のトランザクションBによって変更されたが、まだコミットされていないデータを読み取った場合に発生する.Bがロールバックした場合、トランザクションAは無効なデータを読み出します.これは再読み込み不可と似ていますが、2番目のトランザクションではコミットを実行する必要はありません.
トランザクション1
トランザクション2
原帖住所:http://blog.csdn.net/gaoshan_820822/article/details/4582561
トランザクション同時発生の問題:ダーティリード:あるトランザクションが別のトランザクションにコミットされていないデータトランザクションに読み込まれた1:データの更新----------トランザクション2:トランザクション1更新のレコードトランザクションを読み込む1:コミットのためにcommitを呼び出す***トランザクション2がのデータは、ダーティリードと呼ばれるデータベースメモリに保存されているデータです.***読み込まれたデータはダーティデータとして詳しく説明されています.ダーティリードとは、1つのトランザクションがデータにアクセスし、データが変更されていて、この変更がデータベースにコミットされていない場合、別のトランザクションもこのデータにアクセスし、このデータを使用します.このデータはまだコミットされていないデータなので、別のトランザクションが読み取ったこのデータは汚いデータであり、汚いデータに基づいた操作は正しくない可能性があります.繰り返し不可:同じトランザクションで同じデータを2回読み込み、内容の異なるトランザクションを取得する1:レコードを問い合わせる-------->トランザクション2:トランザクション1クエリーのレコードを更新する-------->トランザクション2:commitを呼び出してトランザクションを提出する1:前回のレコードを再度問い合わせる***このときトランザクション1は同じ1つのデータは2回クエリーされ、得られる内容は異なり、繰り返し不可幻読と呼ばれます.同じトランザクションで同じ操作で2回読み取り、得られたレコード数が異なるトランザクション1:クエリー・テーブル内のすべてのレコード-------->トランザクション2:レコードを挿入-------->トランザクション2:commitを呼び出してコミットトランザクション1:テーブル内のすべてのレコードを再クエリー***このとき、トランザクション1が2回クエリーされたレコードは異なり、幻読詳細解釈と呼ばれます.幻読とは、トランザクションが独立して実行されていない場合に発生する現象です.たとえば、最初のトランザクションがテーブル内のデータを変更した場合、テーブル内のすべてのデータ行に関連します.同時に、2番目のトランザクションもこのテーブルのデータを変更します.この変更は、テーブルに新しいデータを挿入することです.すると,後で最初のトランザクションを操作したユーザがテーブルに変更されていないデータ行があることに気づき,まるで幻覚が起こったかのようになる.
次のような独立性レベルの問題を処理します.
トランザクション・アイソレーションの5つのレベル:TRANSACTION_NONEはトランザクションを使用しません. TRANSACTION_READ_UNCOMMITTEDは汚れた読みを許可します. TRANSACTION_READ_COMMITTEDはダーティリードを防止し、最も一般的な独立性レベルであり、ほとんどのデータベースのデフォルトの独立性レベルTRANSACTION_である.REPEATABLE_READは汚れた読み取りと重複しない読み取りを防止することができ、TRANSACTION_SERIALIZABLEはダーティリードを防止し、繰り返し読み取りや幻読みができず、データベースの効率を低下させる
以上の5つのトランザクション独立性レベルは、Connectionインタフェースで定義された静的定数です.
setTransactionIsolation(int level)メソッドを使用して、トランザクションの独立性レベルを設定します.如:con.setTransactionIsolation(Connection.REPEATABLE_READ);
注意:トランザクションの独立性レベルはデータベースによって制限されます.データベースによってサポートされる独立性レベルは必ずしも同じではありません.
1ダーティリード:変更時に排他ロックをかけ、トランザクションがコミットされてから解放され、読み込み時に共有ロックをかけ、読み出しが完了してトランザクション1のデータを読み出す時に共有ロックをかけた後(トランザクション1がデータを読み出す過程で他のトランザクションはデータを修正しない)、データを操作することは一切許されず、読み取りのみが可能となり、その後1更新操作があれば排他ロックに変換され、他の事務は読み書きに参加する権利がなく、汚い読み書きの問題を防ぐことができます.
しかし、トランザクション1がデータを読み出す過程で、他のトランザクションもそのデータを読み取った可能性があり、読み取りが完了すると共有ロックが解放され、トランザクション1がデータを修正し、修正が完了してトランザクションをコミットし、他のトランザクションが再びデータを読み取る際にデータが一致しないことに気づき、重複しない問題が発生するため、重複しない問題を回避することはできない.
2繰り返して読むことはできません:データを読み取る時に共有ロックをプラスして、データを書く時に排他ロックをプラスして、すべて事務が提出してやっとロックを解放します.読み込み時に他のものにこのデータを修正することは許されず、データがトランザクション中に何度読み込まれても、データは一致しており、重複しない読み取り問題を回避している3幻読み問題:範囲ロックRangeS RangeS_を採用しているSモードでは,ロック検索範囲が読み取り専用であるため,幻影読解の問題を回避することができるが,ここでは範囲ロックを記述する文章がある.
異なる独立性レベルを実行すると、さまざまな問題が発生する可能性があります.次に、それらをまとめ、例を挙げて説明します.
幻読み:幻読みは、2つのまったく同じクエリーが実行されると、2回目のクエリーで返される結果セットが最初のクエリーとは異なる場合に発生します.
発生した場合:範囲ロックはありません.
例:
トランザクション1
トランザクション2
SELECT
* FROM
users
WHERE
age BETWEEN
10 AND 30
;
INSERT
INTO
users VALUES
(3
, 'Bob'
, 27
)
;
SELECT
* FROM
users
WHERE
age BETWEEN
10
AND
30
;
回避方法:シーケンス化された独立性モードを実行すると、どの低レベルの独立性でも発生する可能性があります.
繰り返し不可
ロックベースのパラレル制御方法では、selectを実行するときにリードロックを追加しないと、重複しない読み取りの問題が発生します.
マルチバージョンパラレル制御メカニズムでは、コミット競合に遭遇したトランザクションがロールバックされ、解放される必要がある場合、重複しない読み取りの問題が発生します.
トランザクション1
トランザクション2
SELECT
* FROM users WHERE id=1;
UPDATE
users SET
age = 21
WHERE
id = 1
;
COMMIT; /* in multiversion concurrency*/
control, or lock-based READ COMMITTED *
SELECT
* FROM
users
WHERE
id = 1
;
COMMIT; /* lock-based REPEATABLE READ */
上記の例では、トランザクション2のコミットに成功し、その変更が表示されます.しかし、トランザクション1は他の値を読み出した.シーケンス化および繰返し可能な独立性レベルでは、データベース管理システムは、トランザクション2によって変更される前の値である古い値を返します.コミットされた読み取りとコミットされていない読み取りの独立性レベルでは、更新された値が返される場合があります.これが「繰り返し読み取り不可」です.
この問題の発生を防止するには、次の2つのポリシーがあります.
1.トランザクション1がコミットまたはロールバックされるまで、トランザクション2の実行を延期します.このポリシーは、ロックを使用するときに適用されます.
2.複数バージョンの並列制御では、トランザクション2を先にコミットできます.トランザクション1は、古いバージョンのデータに引き続き実行されます.トランザクション1が最終的にコミットしようとすると、データベースはトランザクション1、トランザクション2の順序と同じ結果を検証します.もしそうであれば、トランザクション1のコミットは成功しました.そうでない場合、トランザクション1はロールバックされます.
汚読
ダーティリードは、あるトランザクションAが別のトランザクションBによって変更されたが、まだコミットされていないデータを読み取った場合に発生する.Bがロールバックした場合、トランザクションAは無効なデータを読み出します.これは再読み込み不可と似ていますが、2番目のトランザクションではコミットを実行する必要はありません.
トランザクション1
トランザクション2
SELECT
* FROM users WHERE id=1
UPDATE
users SET age=21
WHERE id=1;
SELECT
* FROM users WHERE id=1;
COMMIT; /* lock-based DIRTY READ */
原帖住所:http://blog.csdn.net/gaoshan_820822/article/details/4582561