東京大学生産技術研究所 概念情報工学研究センタ 喜連川優 トランザクション処理(続) 東京大学生産技術研究所 概念情報工学研究センタ 喜連川優
Serializabilityの意義 Serializability If a schedule S is conflict equivalent to a serial schedule, then S is correct. オペレーションのインターリーブを可能とし、性能向上に寄与 Serializability test is quite difficult. OS 事前スケジュール 現実的ではない。 適当に実行した後にserializabilityをチェック?
プロトコル 現実的なアプローチ スケジュールをテストする事無くserializabilityを保証するプロトコルを考え出すこと。全てのトランザクションはそのプロトコルに従うものとする。 プロトコル Two phase lock protocol Time Stamp Multi-version
View Serializability これまでの議論はconflict serializability view equivalence Two schedules S and S’ are said to be view equivalent if the following three conditions hold: The same set of transactions participates in S and S’, and S and S’ include the same operations of those transactions. For any operation ri(X) of Ti in S, if the value of X read by the operation has been written by an operation wj(X) of Tj ( or if it is the origin value of X before the schedule started), the same condition must hold for the value of X read by operation ri(X) of Ti in S’. If the operation wk(Y) of Tk is the last operation to write item Y in S, then wk(Y) of Tk must also the last operation to write item Y in S’.
View equivalenceの意味 個々のread操作が2つのスケジュールにおいて同じwrite操作の結果を読むのであれば、read操作は2つのスケジュールにおいて同じ世界を見る(view)ことになるので等価。 Conflict serializabilityとview serializabilityは constrained write assumptionが成り立つ限りにおいて等価 Constrained write assumption:全てのwi(X)はそれに先立つri(X)があり、それのみに依存。 Unconstrained write assumptionにおいては view serializabilityはより緩い。
より柔軟なスケジュール Conflict serializability は時として厳しすぎる 例 debit-credit トランザクション 銀行口座への預け入れと引き出し操作 Serializableで無くとも、正しい結果を生成し得る。 T1:r1(X);X=X-10;w1(X);r1(Y);Y=Y+10;w1(Y); T2:r2(Y);Y:=Y-20;w2(Y);r2(X);X:=X+20;w2(X); Sh:r1(X);w1(X);r2(Y);w2(Y);r1(Y);w1(Y);r2(X);w2(X);
SQLにおけるトランザクション Begin_trans文は無い。SQL文がトランザクションの開始を意味する。 パラメータ Access mode( read only, read write) Diagnostic area size int. Isolation level( read uncommitted, read committed, repeatable read, serializable)
Isolation Level Isolation level Type of violation Isolation Level Isolation level Type of violation Dirty/Read Non-repeatable-read Phantom Read uncommitted Y Y Y Read committed N Y Y Repeatable read N N Y Serializable N N N
Isolation Levelの意味 Dirty Read Nonrepeatable Read Phantom
Concurrency Control 同時実行制御方式 Concurrency Control 同時実行制御方式 ロックに基づく方式 タイムスタンプに基づく方式 多版制御方式 楽観的制御方式
ロックに基づく方式 Binary Locks:2つの状態を有する。(locked, unlocked) LOCK(X):ロックの状態 (1,0) (locked, unlocked) lock_item(X): unlock_item(X):
ロック lock_item(X): クリティカルセクションとして実装 B: if LOCK(X)=0 (*if item is unlocked*) then LOCK(X) ←1(* lock the item*) else begin wait (until LOCK(X)=0 and the lock manager wakes up the transaction); goto B end; クリティカルセクションとして実装
アンロック unlock_item(X): LOCK(X) ← 0;(* unlock the item*) if any transaction are waiting then wake up one of the waiting transactions
Binary Lock 実装:極めて簡易 ロックテーブル Binary Lock 実装:極めて簡易 ロックテーブル <data item name, LOCK, locking transaction> + 待ちトランザクションキュー
Shared/Exclusive Locks Shared/Exclusive Locks Binary Lockは制約が強すぎる。 読む場合には多くのトランザクションが同時に読み出すことを許すべき 書き込む場合には排他制御が必須 Multi-mode Lock Shared/Exclusive Lock, 別名 read/write lock 3つの操作 read_lock, write_lock, unlock LOCK(X): read-locked(shared-lock), write-locked(exclusive- lock), unlockedの3状態
実装 ロックテーブル構造 <data item name, LOCK, no_of_reads, locking_transaction(s)> LOCKがwriteの時はnoは1, readの時は待ちトランザクション数 read_lock(X), write_lock(X), unlock(X)
read lock__ read_lock(X): B: if LOCK(X)=‘unlocked’ then begin LOCK(X) ←‘read_locked’; no_of_reads(X)←1 end else if LOCK(X)=‘read_locked’ then no_of_reads(X)←no_of_reads(X) + 1 else begin wait(until LOCK(X)=‘unlocked’ and the lock manager wakes up the TR); goto B end;
write lock write_lock(X): B:if LOCK(X)=‘unlocked’ then LOCK(X) ← ‘write_locked’ else begin wait(until LOCK(X)=‘unlocked’ and the lock manager wake up TR); gotoB end;
unlock unlock(X): if LOCK(X)=‘write_locked’ then begin LOCK(X)←‘unlocked’ wakeup one of the waiting TR, if any end else if LOCK(X)=‘read_locked’ then begin no_of_reads(X)←no_of_reads(X) ー1 if no_of_reads(X) = 0 then begin LOCK(X)←‘unlocked’; wakeup one of TR, if any end;
lock conversion 最初にread_lock(X) , 後からwrite_lock(X)にupgrade Read_lockを持っているトランザクションが一つだけの場合、upgrade可能、そうでない場合は待つ 最初にwrite_lock(X),後からread_lock(X)にdowngrade
lockとserializability 次ページの例 Unlock操作が早すぎて適正な結果を生まない。
Unlockが早すぎる例 (C)は誤った結果を生む
Two Phase Lock (2相ロック) Two phase locking protocol Two Phase Lock (2相ロック) Two phase locking protocol 全てのロック操作が終了した後、アンロックする ロックフェーズとアンロックフェーズが分離 expanding/growing phase(ロック獲得)とshrinking phase(ロック開放)に分離 Lock upgradeはexpanding phaseにおいて、lock downgradeはshrinking phaseにおいて実行可
例の2相化 T1 T2 read_lock(Y); read_lock(X); read_item(Y); read_item(X); T1 T2 read_lock(Y); read_lock(X); read_item(Y); read_item(X); write_lock(X); write_lock(Y); unlock(Y); unlock(X); read_item(X); read_item(Y); X:=X+Y; Y:=X+Y; write_item(X); write_item(Y); unlock(X); unlock(Y);
2相ロックとserializability 全てのトランザクションが2相ロックプロトコルに従う場合、当該スケジュールは直列可能である。 2相ロックはある程度の並行性を犠牲にしている。しかし、serializability チェック不要というメリットの代償と言える。
Variations Basic 2PL:これまでの定義 Conservative 2PL(Static 2PL) Strict 2PL トランザクションは実行開始以前に全てのロックを取得(pre-declaration) デッドロックフリー 実際には全てを申告するのは現実的でない Strict 2PL コミット・アボート時点まで全てのexclusiveロックを開放しない。 Strict scheduleを実現 デッドロックフリーではない
conservative 2PL : shrinking phaseのみ rigorous 2PL: expanding phaseのみ コミット・アボート時点まで全てのロックを開放しない。 conservative 2PL : shrinking phaseのみ rigorous 2PL: expanding phaseのみ
Deadlock and Starvation T1 T2 read_lock(Y) read_item(Y) read_lock(X) read_item(X) write_lock(X) write_lock(Y)
Deadlock prevention protocol 必要なロックを実行前に全て獲得する Conservative 2PLで利用される手法 一つでもロック出来ないデータがあると、何れのデータもロックしない。一定時間待ち、リトライする。 現実的でない為実際には利用されることは無い
Deadlock prevention protocol(2) データベースの全てのデータに順番を付けて、その順にロックする手法 プログラマが順序を気遣うのは非現実的
Transaction time stamp based methods Timestamp TS(T) T:transaction, the starting time of the transaction T. TiがXのロックを獲得しようとするが、Tjが既に当該ロックを有する場合の手順 Wait-die: If TS(Ti) < TS(Tj), then (Ti is older than Tj) Ti is allowed to wait; otherwise(Ti is younger than Tj) abort Ti(Ti dies) and restart it later with the same timestamp Wound-wait: If TS(Ti) <TS(Tj) then (Ti is older than Tj) abort Tj(Ti wound Tj) and restart it later with the same timestamp; otherwise (Ti younger than Tj) Ti is allowed to wait.
wait-dieとwound-die Wait-die Wound-wait: wait-dieの逆 両手法ともデッドロックフリー 古いトランザクションは若いトランザクションを待つことが許される。 Wound-wait: wait-dieの逆 古いトランザクションが若いトランザクションと競合すると若いトランザクションをアボートする。 両手法ともデッドロックフリー 常に待つ方向が一定。例えばwait-dieでは古い方が若い方を待つ
no waiting / cautious waiting (デッドロックフリー) If Tj is not blocked( not waiting for some other locked item), then Ti is blocked, otherwise abort Ti. No waitingの改良
Deadlock detection and timeouts トランザクション間の競合が少ないと予想される場合は得策。 長いトランザクション、多くのデータを参照するトランザクションでは不適切 Wait-for graph Ti → Tj : トランザクションTiがトランザクションTjの有するロックを待つことを示す サイクル:デッドロック
種々の側面 いつデッドロック検出を行うか? Victim selection タイムアウト ロック待ち時間が閾値を越す場合 同時実行トランザクションが一定数を越える場合 Victim selection 長時間走行し、多くの更新を行ったトランザクションを選択しないようにする。 タイムアウト 一定時間以上待ちが発生すると、デッドロックが実際に発生しているかどうかによらず、アボートする。簡単に実装可能なため良く利用される。
Starvation 特定のトランザクションが長時間に渡り待たされ、他のトランザクションは正常に処理される場合 フェアなスケジューリングがなされていないことによる。 プライオリティを付加しても良いが、待ち時間がたつにつれて、プライオリティを上げる 常にvictimに選択されないように、何度も選ばれるとそのプライオリティを上げるなどして回避する。
Timestampに基づく 同時実行制御方式 Timestamp トランザクションを識別するためにDBMSによって生成されたユニークな値 (通常)トランザクション投入時刻 TS(T) ロックを利用しないので デッドロックフリー timestampの付け方 トランザクション毎に整数を付与。1づつ増やす 時刻を利用。完全に同時に2つのトランザクションが駆動されることが無いことを保証しておく。
TOアルゴリズム タイムスタンプ順にserializableにする。 したがって TO timestamp orderingと呼ばれる Read_TS(X): read timestamp of itemX Xを読むことが出来たトランザクションのタイムスタンプの中で最大の値 Read_TS(X)=TS(T) T:Xを読んだ最も若いトランザクション Write_TS(X): write timestamp of X Xに書き込むことの出来たトランザクションのタイムスタンプの値で最大のものを指す。
Basic TO algorithm トランザクションTがread_item(X), write_item(Y)を発行する時点でトランザクションのタイムスタンプと read_TS(X), write_TS(X)を比較。 トランザクションのタイムスタンプ順序が正しいかどうかをチェック。 順序が不正な場合には当該トランザクションをアボート、新しいタイムスタンプを付加して再投入 あるトランザクションがアボートするとそれの書いたデータを参照したトランザクションもアボートする必要がある(cascade rollback)
Basic TO Tが write_item(X)を発行すると Tが read_item(X)を発行すると 特徴: If read_TS(X)>TS(T) or if write_TS(X)>TS(T) Then abort and rollback T Else write_item(X), set write_TS(X) to TS(T) Tが read_item(X)を発行すると If write_TS(X)>TS(T) then abort and rollback T If write_TS(X) <=TS(T), then read_item(X) and set read_TS(X) to the larger of TS(T) and the current readTS(X) 特徴: 2PLと同様にserializable (許容クラスはそれぞれ異なる) デッドロックフリー
Strict TO Strictにすることにより cascadeless Strict TO Strictにすることにより cascadeless TS(T)>write_TS(X)の場合、TS(T’)=write_TS(X)なるT‘がコミットするまでread/writeを延期させる。 実現のためには ロックに相当する機構が必要となる(デッドロックフリー)
Thomas‘s Write Conflict serializabilityは保証されない。書き込みrejectをより少なくする効果を有する。 If read_TS(X)>TS(T) then abort and rollback T If write_TS(X)>TS(T) then do not execute write operation but continue! write_item(X) could be ignored. 問題が生じると上の条件で検出される。 If neither of the above conditions occurs, Then execute the write_item(X) operation