データベース・トランザクション、ロック
10591 ワード
トランザクションフィーチャー
第一に、原子性、すなわち不可分性;第二に、一致性、データ更新前後と業務の一致性を保証する.第三に、隔離性、複数の事務は影響しない.第四に、永続性、トランザクションのコミット後、データは永続的にヘテロデータベースに格納されます.
独立性レベル
コミットされていないトランザクションを読み込み変更または新規作成すると、前のトランザクションがコミットされていないデータを読み込むことができ、ダーティリードが生成されます.読み取りコミット(oracleデフォルトの独立性レベル)1つのトランザクションが変更または追加された後、コミットされていない場合、別のトランザクションは読み取りできません.コミットされたトランザクションのデータのみを読み込むことができます.2回連続して読み取ると、1回目のデータが2回目のデータの中で多かれ少なかれ読み返されない場合があります.繰り返し読み込み(MySQLのデフォルトのトランザクション独立性レベル)1つのトランザクションは読み込み中であり、もう1つのトランザクションは書き込めません.幻読みになるかもしれません.シーケンス化各行について、1つのトランザクションは読み取り中であり、もう1つのトランザクションは読み取りまたは書き込みできません.
汚い読み、繰り返してはいけない読み、幻読みの意味
ダーティリード:あるトランザクションは、別のトランザクションがコミットしていないデータを読み込むことができます.
繰り返し不可:1つのトランザクションで異なる期間のクエリに異なる結果が表示され、更新によって削除される可能性があります.
幻読み:1つのトランザクションで異なる期間にクエリーされ、レコード数が異なります.再読み込み不可との違いは、幻読みではすでに読み込まれたデータは変更されませんが、以前に比べてクエリー条件を満たすデータが多くなります.
Oracleデータベースでは、READ COMMITTEDとSERIALIZABLEの2つのトランザクション独立性レベルがサポートされています.
ロック
データベースの大規模な同時操作は、デッドロックとロックのパフォーマンスの問題を考慮します.データベース・システムのACIDプロパティでは、データベース・システムが同時に実行される各トランザクションを分離する能力を有し、相互に影響を及ぼさないようにする必要があることを意味します.データベースはロックを使用してトランザクションの独立性を実現します.ロックの基本原理は、1、トランザクションがデータベース・リソースにアクセスする場合、select文を実行するには共有ロックを取得する必要があり、insert、update、delete文を実行する場合は、操作されたリソースをロックするために独占ロックを取得する必要があります.2、2番目のトランザクションが同じリソースにアクセスする場合、対応する文もまず対応するロックを取得する必要があります.この場合、状況に応じて2番目のトランザクションがロックを待機するか、すぐにロックを取得できるかを決定できます.
ロックの基本種類
行レベルロック
行レベルのロックは排他的なロックであり、他のトランザクションがこの行を変更することを防止します.次の文を使用すると、Oracleでは行ロックが自動的に適用されます.
INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT];
SELECT…FOR UPDATE文は、ユーザーが一度に複数のレコードをロックして更新することを許可するCOMMIT文またはROLLBACK文を使用してロックを解除する
テーブルレベルロック
T1: select * from table
T2: update table set column1='hello'
: T1 ( ) T2 If T1 T2 ...... else T2 endif
T 2が待つのは、T 2がupdateを実行する前にtableテーブルに排他ロックを追加しようとしたためであり、データベースは同じリソース上で共有ロックと排他ロックを同時に共存できないことを規定している.したがって、T 2は、T 1の実行が完了し、共有ロックが解放されてから、update文の実行が開始されるまで、排他ロックを追加する必要があります.
T1: select * from table T2: select * from table T2 T1 , 。 : T1 , table , lockA T2 , table , lockB。
2つのロックは、同じテーブルなど、同じリソースに同時に存在することができます.これは共有ロックと共有ロックの互換性と呼ばれます.これは、共有ロックは他のセッションがリソースを同時に読むことを阻止しないが、他のセッションupdateを阻止することを意味する.
T1: select * from table T2: select * from table T3: update table set column1='hello'
今回、T 2はT 1が完了するのを待たずに実行できますが、T 3はT 1とT 2が完了するのを待たなければ実行できません.T 3はT 1とT 2の共有ロックがすべて解放されるまで待たなければならないので、排他ロックを行ってupdate操作を実行することができない.
T1:
begin tran select * from table(updlock) ( ) update table set column1='hello' T2: begin tran select * from table(updlock) update table set column1='world'
更新ロックとは、「私は今読みたいだけです.他の人も読むことができますが、将来更新操作をする可能性があります.共有ロックから排他ロック(更新用)までの資格を取得しました」という意味です.トランザクションには更新ロックが1つしかありません.
T 1はselectを実行し、更新ロックを加える.T 2は運行して、更新ロックを加えるつもりですが、すでに1つの更新ロックがそこにあることに気づいて、待つしかありません.
後でuser 3、user 4...tableテーブルのデータをクエリーする必要がある場合、T 1のselectが実行されているためブロックされることはなく、クエリーすることができます.更新ロックは共有ロックと共存できます.
T1: update table set column1='hello' where id<1000 T2: update table set column1='world' where id>1000 T1 ,T2 , T1 id<1000 . T2 update。 id T1: update table set column1='hello' where id<1000 T2: update table set column1='world' where id>900
T 1先達、T 2はすぐに到着し、T 1に加えられた排他ロックはT 2のupdateをブロックする.
テーブルの行に排他ロックが付加されると、テーブルはロックされません.データベース・プログラムは、テーブルがロックされていないことをどのように知っていますか?1つの方法は、テーブルの各レコードに排他ロックがあるかどうかを1つずつ判断することであり、もう1つの方法は、テーブルという階層でテーブル自体に意向ロックがあるかどうかを直接チェックし、1つずつ判断する必要はありません.明らかに後者は効率が高い.
T1: begin tran select * from table (xlock) where id=10 -- id=10 T2: begin tran select * from table (tablock) --
仮にT 1が先に実行され、T 2が実行され、T 2が実行されると、テーブルロックを追加しようとすると、テーブルロックを追加できるかどうかを判断するために、データベースシステムはtableテーブルの各行の記録に排他ロックがあるかどうかを1つずつ判断し、そのうちの1行に排他ロックがあることが発見された場合、テーブルロックを追加することは許されない.ただ、このように一つ一つ判断するのは効率が低すぎる.
実際、データベースシステムはこのように動作しません.T 1のselectが実行されると、システムはテーブルtableのid=10のこの行に排他ロックを追加し、同時にこっそりテーブル全体に意向排他ロック(IX)を追加し、T 2がテーブルロックを実行すると、このテーブルがすでに意図排他ロックが存在していることを見るだけで、リソースを逐条検査する必要はありません.
T1: begin tran update table set column1='hello' where id=1 T2: begin tran update table set column1='world' where id=1
この例は上記の例と実際の効果は同じで、T 1は実行して、システムはtableに対して同時に専門家に対して他のロックを並べて、ページに対して意向を加えて他のロックを並べて、表に対して意向を加えて他のロックを並べます.
DDL文にはSch-Mロックが追加されます.このロックでは、他のセッションがテーブルに接続できません.このテーブルにもつながっていません.もちろん、このテーブルに対して何のsql文を実行したいのかは言うまでもありません.
jdbcでデータベースに新しいsql文を送信しました.データベースはまずそれをコンパイルし、コンパイル中にもロックをかけます.Schema stability(Sch-S)locksと呼ばれています.
select * from tableA
この文のコンパイル中、他のセッションはテーブルtableAに対して任意の操作(update、delete、排他ロックなど)を行うことができますが、DDL(alter tableなど)操作はできません.
楽観ロックと悲観ロック
この2つのロックはアプリケーションで実現され、データベースの下部にはこの2つの機能がありません.主にプログラムの同時性を高めるためです.
悲観的なロックとは、データベース・メカニズムに基づいて実現されます.たとえばselect句を使用するときにfor updateを付けると、句を変更するトランザクションが終了するまで、どのアプリケーションもselectからのレコードを変更できません.
楽観的ロックとは、アプリケーションのバージョンメカニズムに基づいて実現される.通常、テーブルにバージョンフィールドvが設計されます(通常、このフィールドをtimestampに設定します).一般的なupdateシーンは次のとおりです.
select a, v from tb where id=1;
:['xxx', 11111]
update tb set a='yyyy', v=systimestamp where v=11111;
// , v
これは、update操作のたびにバージョンフィールドを変更する必要があります.そうしないと、プロセス間のデータが上書きされます.
楽観的なロックでは、他のアプリケーションのデータに対する操作をロックできません.楽観ロックと悲観ロック