Chapter 18 concurrency control Techniques 本章の内容 並列制御を行うために... lockを使用するプロトコル timestampを使用するプロトコル multiversionプロトコル validationプロトコル data item,lockの粒度について Index使用時に発生する並列制御に関する問題 その他の並列制御に関する問題 Binary lock シンプルな仕組みのロック X 0 →Xはロックされていない X 1 →Xはロックされている と定義する。 ロックされていたらロックが解除される(0になる)まで待つ。 ロックされていなかったらロックをして(1に変更)からXを操 作。Xに対する操作が終わったらロックを解除(0に変更) Binaly lockは1つのトランザクションしかitemにアクセ スできない。 →効率が悪い Shared/Exclusive(Read/Write) lock Binaly lockの効率の悪さを改善 特徴 Readはitemの状態を変更しないのでreadをするトランザクション同士 なら共有できるようにする。Writeはitemの状態を変更するので排他 的(ひとつのトランザクションしかロックがかけれないよう)にする。 readするときに行うロックをRead(Shared) lock, writeするときに 行うロックをWrite(Exclusive) lockという。 Read lockしているトランザクション数を記憶するようにする。 Transaction_0 Transaction_1 Transaction_2 X:Read_lock_count: 3 1 2 0 Lock Conversion ロックの状態を変更することもできる。 ただし、変更するための条件がある。 Read lock→Write lock (upgrade) Transaction_0 Transaction_1 X Transaction_2 1つのトランザクション しかReadしていない 場合のみupgrade可能 Write lock→read lock (downgrade) Transaction_2 X もともと1つのトランザク ションしかロックして いないのでいつでも downgrade可能 直列化可能性の保証 トランザクションを並列に実行し たときとある順序によって逐次実 行したときで結果が同じになるこ とを直列化可能性という。 →並列処理ではこの直列化可能性を 保証することが非常に重要 右のスケジュールはa→b又はb→a といった具合に並び替えることは 出来ない。 aがYを読み取るのが早すぎて bの変更が反映されていない Binary lock, Read/Write lock ではこのような誤ったスケジュールが 生じる可能性がある。 Transaction_a Transaction_b read_lock(Y) read_item(Y) unlock(Y) read_lock(X) read_item(X) unlock(X) write_lock(Y) read_item(Y) Y <- X+Y write_item(Y) unlock(Y) write_lock(X) read_item(X) X <- X+Y write_item(X) unlock(X) Two phase lock(2PL, 2相ロック) ロックを解除する前に全てのread lockとwrite lockを 済ませる。 Transaction X X Y Y Z Z expanding phase: read,write lock,(upgrade) shrinking phase: ロック解除,(downgrade) スケジュールをチェックしなくても直列化可能性が保証される その代わり、使い終わったitemでもロックし続けるので並列 性を損なう(トレードオフ) 様々な2PL conservative 2PL read-set,write-setをあらかじめ宣言し、ロックしてからトランザクション を開始する。→ shrinking phaseからスタートする形になる。 deadlock-free しかし、実際はあらかじめ宣言した集合以外のモノも後で必要になることが 多々あるので実用上、使えない。 strict 2PL 実用でよく使われる方式。strict scheduleを保証。 deadlockに陥る可能性がある。 トランザクションがcommitかabortされるまでwrite lockを全く解除しない。 rigorous 2PL strict 2PLを更に制限的に。strict scheduleを保証。 こちらもdeadlockに陥る可能性がある。 トランザクションがcommitかabortされるまでread/write lockを全く解除 しない。→トランザクションが終わるまで、ずっとexpanding phase Deadlock ロックを使用することで生じる新たな弊害 例 transaction_a transaction_b read_lock(Y) read_item(Y) read_lock(X) read_item(X) write_lock(X) write_lock(Y) トランザクションaはXをロックして いるbを待ち、トランザクションbは Yをロックしているaを待つ。 お互いを永遠に待つ続ける現象。 Deadlock 防止プロトコル deadlockを防ぐ方法のうちのひとつ。 conservative 2PLで使用した(非現実的な)方法もこれに含まれる。 他にもいくつかのdeadlock防止 プロトコルがある deadlockを起こすかもしれない2つのトランザクションをどう処理す るのか決定する。ロックが衝突したら... →Wait-die & Wound-die Wait-die:古いトランザクションが新しいトランザクションを待つ。 Wound-die:新しいトランザクションが古いトランザクションを待つ。 最終的にWait-dieでもWound-dieでも新しい方のトランザクション をabortする。 deadlock-freeだが、必要以上にトランザクションのabortや restartを発生させるかも。 Deadlock 防止プロトコル その2 Wait-dieやWound-dieでは古いトランザクションか新しいトランザク ションか知らないとできないので、トランザクションが生成された順番 に関する情報(transaction timestamp)が必要になる。 このような情報が不要な手法 no waiting:待たされるようなら即abort。その後しばらくして、 restart。 →abortが多発するおそれがある。 cautious waiting:no waitingよりも不要なabortを減らすため に提案された手法。2つのトランザクションaとbがあり、bがある項目X を先にロックしていると仮定すると以下の規則に従う。 bが他のトランザクションにブロックされてなければaは待機可能。bがブ ロックされていたらaをabort。 この規則により、ブロック時間の大小でトランザクションの順序づけが 可能となる。→deadlock-free しかし、Deadlock防止プロトコルは非現実的な想定やオーバーヘッドが大 きいため実用ではあまり使われない。 Deadlock Detection,Timeout 実際によく使われるのはDeadlock DetectionやTimeoutを使う方法 Deadlock Detection Deadlockを検出するためにwait-for graphというグラフ を構築する。 例 2つのトランザクションa,bがitem X,Yをそれぞれロックしようとする。 1. aが先にXをロック 2. bがYをロックし、Xをロックしようとしてaを待つ 3. aがYをロックしようとしてbを待つ wait-for graph上で 輪っかが出来た X a b Y deadlockが発生している Deadlock Detection,Timeout Deadlock Detection(のつづき) deadlockの発生が検知されたらabortさせる トランザクションを選択する。 abortさせるトランザクションを選ぶことを victim selection(いけにえの選択)と呼ぶ。 通常は軽いトランザクションの方をabortさせる。 X a b Y Timeout システムで定義された時間よりもトランザクションの待機時 間の方が長かったらabortさせる。 単純でオーバーヘッド小なので実用的。 Starvation あるトランザクションが実行している間、もう一方の あるトランザクションが全く実行できなくなる現象。原因として… トランザクションに割り当てる優先度が不正 victim selectionが毎回同じトランザクションを選ぶ が挙げられる 回避方法 公平な優先度の割り当て abortしたトランザクションの優先度を次回から徐々に上げていく賢い victim selectionの導入 Timestamp Ordering(TO) トランザクションが生成された日付時刻情報を基にトラ ンザクションを実行していく手法。 ロックを使用しないのでdeadlockが起きない。 Basic TO トランザクションの実行順番に矛盾がないかチェックするために各 itemにそのitemをread,writeしているトランザクションの中で最も 大きい(=新しい)timestamp値を持たせるようにする。 実行してるトランザクションTのtimestampよりitemが持っている timestampの方が新しかったらどこかで矛盾が生じたことになるので、 Tをabort。 →Tが書き込んだitemを使用する予定のトランザクションも abortしなければならない!(cascading rollback) Timestamp Ordering(TO) その2 Basic TOはスケジュールが復元可能であることを保証しないという問題 点がある。これに対処する代替案がいくつかある。 Strict TO Basic TOの改良型。 readやwrite命令をすぐに実行せず、他のトランザクションがコミット 完了するまで遅延して発行させることでstrict scheduleであること と競合直列可能であること両方を保証 Thomas's Write Rule こちらもBasic TOの改良型。 競合直列可能であることは保証しないが、write命令時のチェックを 改良することにより、write命令の排除の発生数に抑えている。 競合直列可能とは? 二つのトランザクションが同じ項目を操作しようとしていて 更に片方がwriteしようとしていたら”競合する”という。 transaction_a read(X) write(Y) transaction_b X Y write(X) read(Y) 更に競合する基本操作の手順が同じなら競合等価であると いう。 競合直列可能→並列に実行されるスケジュールがある順序 で逐次実行されるスケジュールと競合等価なことを指す。 Multiversionプロトコル itemに対して複数のバージョン(履歴)を持つ。 適切なバージョンを選ぶことでスケジュールを直列化可能にする。 複数のバージョンを保持するために多くの記憶領域が必要となる。 しかし最近では他の手法もリカバリーのためにいくつかの履歴を 保持しているのであまりに大きなデメリットというわけではない。 timestampがベースになっているものと2PLがベースになってい るもの計2種類ある。 TOベース,2PLベースのMultiversion TOベース writeしたらversionを+1する writeしたトランザクションがabortしてもその後ろに控えているトラン ザクションはabortせず、適切なversionをreadする。 しかし、これだけではcascading rollbackの完璧な対策にならず、 結局writeするトランザクションがコミット完了するまで他のトランザク ションが待つ必要がある。(書き込む前に他のトランザクションが読み込 んだらマズイ!) 2PLベース read/writeにcertifyモードを加える。 itemに2つのバージョンを持たせ、片方をread時に提供することでread lockとwrite lockを共有化(ただしwrite lock同士は共有できない) トランザクションのコミット時にwriteした全てのitemのcertify lockを 取得し、read時に提供しているitemのversionを上げる。(certify lockは他の2つのlockと排他的) Validation(Optimistic) プロトコル 3つの段階からなる Read Phase Validation Phase Write Phase read~validation phaseまでのオーバヘッドは極めて小さ い(というかRead以外に何もしてない) validationでトランザクションの衝突がなかったかチェックし、 してなかったらwriteを実行。していたらabortし、再実行。 →衝突がほとんど起こらないと言うことを期待しているので楽観的な (Optimistic)プロトコルと呼ばれる。 data item,lockの粒度 ↑小 data itemの大きさ(=粒度)は数種類ある ↓大 recordのフィールド単位 record単位 ディスクブロック(ページ)単位 ファイル単位 DB全体 ロックをかけるdata itemが大→並列性が損なわれる。 ロックをかけるdata itemが小→並列性は高まるが、より多くのlock命令や unlock命令が発行され、itemを操作するためのオーバーヘッドが大きくなる。 並列性とシステム全体にかかるオーバーヘッドはトレードオフの関係にある。 →bestな粒度はトランザクションの内容によって決まるので大抵のDBMSには 複数の粒度レベルでロックがかけられるようになっている。 複数の粒度レベルが存在する場合の問題点 粒度が小さいものに対してロックをかける(ロックの粒度小) 例.recordにロックをかける そのrecordを保有するディスクブロック(更にそのディスクブロックを持つファ イル)に排他ロックがかかっていないかチェックする チェックする数は少ない 粒度が大きいものに対してロックをかける(ロックの粒度大) 例.ファイルにロックをかける ファイルが保有する全てのディスクブロック、更にそのディスクブロックが保有 するrecord全てに排他ロックがかかっていないかチェックする必要がある チェックする数が多すぎ このままでは実用にならない。 →そこでintension lock Intension lock itemの粒度順にtree構造にした 階層図を作成し、このtree上の目 的のnodeからrootまでのpathに どのようなロックがかかっているの かトランザクションに知らせることで (大量の)チェックを省く。 DB file page file page record page record record record Shared/Exclusiveの2つ以外に3つのlockモードを追加。 Intension Shared(IS) :ノードの子からShared lockを要求されてる Intension Exclusive(IX) :ノードの子からExclusive lockを要求さ れてる Shared-intension Exclusive(SIX) : 上記2つが混ざった状態 Index使用時に発生する並列制御に関する問題 Index...データの検索速度を向上させるために、どの行がどこ にあるかを示した索引のこと。 このIndexに対してtwo-phase lockをかけることもできる。 しかし、Indexの検索は前ページの木構造のrootから開始する。 小さなrecordをwrite 又は insertしようとするとrootに排他 ロックをかけることになり効率が非常に悪い。 Index使用時に発生する並列制御に関する問題 もう少し効率を上げるには? page 1. rootを排他ロック 2. 子ノードに空きが無ければ その子ノードも排他ロック。 DB file record 3. 子ノードに空きがあればrootの排他 ロックを解除して他のトランザクション がすぐアクセスできるようにする。 page page record 4. そしてそのノードの子としてrecordをinsert。 (分割が発生するようならば親のノードに再び排 他ロックをかけて分割作業を行う) file record record その他の手法として同じ階層のノードとリンクする構造を持つB-link treeの 利用などがある。 この手法ではleafの分割を招くようなinsertとsearchを並列に走らせても searchが成功するかもしれないというメリットを持つ。 その他の問題 phantom probrem 以下のようなスケジュールがあるとする transaction_a transaction_b select * from A; insert into A values(..,..); select * from A; トランザクションbの最初の selectと次のselectで結果 が異なる→index lockで対 処できる interactive transaction まだコミットされてないトランザクションの値を対話式デバイスを介して読 み込み、それを他のトランザクションに書き込んだりしたときに不整合が発 生する問題のこと→コミットされるまで対話式デバイスへの入出力はしない ようにする。 Latche 瞬間的な排他ロック。例えばメモリー上のバッファからdiskに書き込む際等 に見られる。→ロックと同様にパフォーマンス低下の原因となる。
© Copyright 2024 ExpyDoc