[DB][DB2] LOCK

■ロックの対象
DB2は暗黙的にロックを取得する。

ロックの対象
 行の更新は行単位のロックを使用すれば並行性が高まる。
 →行ロック。
 が、DROP TABLE中の表に対しては、SELECTを許さない制御にすべき。
 →表ロック。
 ユーティリティでは表スペースを占有使用したいものもある。
 →表スペースロック。
 
 *アプリは、行ロックと表ロックをとる。
 *ユーティリティは、行ロック、表ロック、表スペースロックをとる。

□ロックのモードと互換性
同一行の更新を行う2つのアプリが同時に起動されても
一方の更新が終わるまで他方の更新は待たされるべき。
一方、
読み取りアプリ同士は、互いに待つ必要はない。
これら同時並行稼動性の制御を
DB2は、ロックのモードとその互換性(相手のロック解放を待つ/待たない)で実現。

ロックモードは全12種類
互換性は12x12パターン

ロックの期間
分離レベルに応じてロックの保持される期間が変わる。

-分離レベルRS/RR : 一度獲得した共有ロックを基本的にCOMMIT/ROLLBACKまで保持する。
-分離レベルCS : 共有ロックは基本的にカーソルが別の行へ移動するまで保持する

更新のためのロックもトランザクション終了まで保持される。
更新ロックを保持することで他トランザクションからの更新が防止される。

□ロックの範囲
分離レベル【RR
 [SELECT]で読み取った[検索行全て]に[共有ロック]が取られる。
 ※索引の次の行もネクストキーロックとして共有ロックが取得される。
分離レベル【RS
 [SELECT]で得られた[結果行全て]に[共有ロック]が取られる。
分離レベル【CS
 [カーソル位置の行]に[共有ロック]が取られる。
分離レベル【UR
 共有ロックは取られない。
 ※ゆわゆるダーティリード。
  他のトランザクションが更新中の値も読む。

*ネクストキーロック
 DB2 V7以前の仕組み
 オプションDB2_RR_TO_RS=YESレジストリ変数で無効に出来る

*タイプ2索引
 ネクストキーロックの使用を最小限に抑え
 同時稼動性を向上させるDB2 V8.1の新機能

*インデックス
 表にインデックスを張ってない場合
 RRはSELECT文で表全体にSロックを掛け、
 UPDATE文は表にSIXを掛ける。
 →デッドロックが発生し易い。


■FOR UPDATE OF
更新を掛ける行に、SELECT FOR UPDATE WITH RSでUロックを掛けた後に、
UPDATE文のXロックを掛ける。
→システム全体で1度に1つのロジックだけがXロック掛けることになる。
※デッドロックを回避できるが並行性は落ちる。

□デッドロックの背景
 行の列の現在値読み取り、更新するタイプのアプリでは、
 FOR UPDATE OF付きのカーソルを使用しないとデッドロックが起き得る。
 →共有ロック同士がが互換で共有ロックと排他ロックが非互換のため。

  TXN1: SELECT TBL1 COL1 (共有ロック) →LOCK A
  TXN2: SELECT TBL1 COL1 (共有ロック) →LOCK B
  TXN1: UPDATE TBL1 COL1 (排他ロック) →LOCK Bの開放待ち
  TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK Aの開放待ち

□デッドロック排除
 UPDATE WHERE CURRENT OFカーソルを使うと、
 更新ロック(Uロック)が使われ、デッドロックが避けられる。

  TXN1: SELECT TBL1 COL1 FOR UPDATE OF (更新ロック) →LOCK A
  TXN2: SELECT TBL1 COL1 FOR UPDATE OF (更新ロック) →LOCK Aの開放待ち
  TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK Aの開放待ち
  TXN1: UPDATE TBL1 COL1 (排他ロック) →LOCK A
  TXN1: COMMIT →LOCK Aの開放
  TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK B
  TXN2: COMMIT →LOCK Bの開放

□注意点
 *FOR UPDATE付きSELECTは分離レベルCSで使う
  -ロックの開放が早いCS(TRANSACTION_READ_COMMITED)で使う。
  -更新トランザクションではRRRSを使う必要がない。
 *FOR UPDATE付きSELECT発行前にはロックを開放しておく
  同じ行に対して
  ・FOR UPDATEなしSELECT
  ・FOR UPDATE付きSELECT/UPDATE
  を行うトランザクションが2つ並行実行されるとデッドロックになり得る。
  
  ×
   TXN1: NS/S →LOCK A
   TXN2: NS/S →LOCK B
   TXN1: U (LOCK A)
   TXN2: U →LOCK Aの開放待ち
   TXN1: X →LOCK Bの開放待ち
   TXN1: (commit)
   TXN2: (x)
  ○
   TXN1: NS/S →LOCK A
   TXN2: NS/S →LOCK B
   TXN1: COMMIT →LOCK Aの開放
   TXN2: COMMIT →LOCK Bの開放
   TXN1: U →LOCK C
   TXN2: U →LOCK Cの開放待ち
   TXN1: X (LOCK C)
   TXN1: COMMIT →LOCK Cの開放
   TXN2: X →LOCK D
   TXN2: COMMIT →LOCK Dの開放


■ロック変換
連続して発行されるSQLによって取得されるロックのモードがより強いモードに代わること。

例えば、
FOR UPDATE OF付きカーソルによるFETCH後のUPDATEでは、
更新ロック(Uロック)が排他ロック(Xロック)に代わる。
※Uロックは一度開放されてXロックが取られるのではなく、
 ロックが保持されたままでロックモードが排他ロック(Xロック)に変わる。
 →ロックの変換時に、他トランザクションにロックを略奪されない。

  TXN1: SELECT TBL1 COL1 FOR UPDATE OF (更新ロック) →LOCK A
  TXN2: SELECT TBL1 COL1 FOR UPDATE OF (更新ロック) →LOCK Aの開放待ち
  TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK Aの開放待ち
  TXN1: UPDATE TBL1 COL1 (排他ロック) →LOCK A ★ロック変換
  TXN1: COMMIT →LOCK Aの開放
  TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK B
  TXN2: COMMIT →LOCK Bの開放

□更新ロックの互換性
FOR UPDATE OF付きカーソルによるFETCH後のUPDATEの流れでは、
非互換の更新ロックと更新ロックは排他され、更新処理がシリアライズされる。

 ・共有ロック(S/NS) ← 共有ロック(S/NS) : 互換(待たない)
 ・共有ロック(S/NS) ← 更新ロック(U) : 互換(待たない)
 ・共有ロック(S/NS) ← 排他ロック(X) : 非互換(相手のロック解放を待つ)

 ・更新ロック(U) ← 共有ロック(S/NS) : 互換(待たない)
 ・更新ロック(U) ← 更新ロック(U) : 非互換(相手のロック解放を待つ)
 ・更新ロック(U) ← 排他ロック(X) : 非互換(相手のロック解放を待つ)

 ・排他ロック(X) ← 共有ロック(S/NS) : 非互換(相手のロック解放を待つ)
 ・排他ロック(X) ← 更新ロック(U) : 非互換(相手のロック解放を待つ)
 ・排他ロック(X) ← 排他ロック(X) : 非互換(相手のロック解放を待つ)

 TXN1: SELECT TBL1 COL1 FOR UPDATE OF(更新ロック) →LOCK A
 TXN2: SELECT TBL1 COL1 FOR UPDATE OF(更新ロック) →LOCK Aの開放待ち
 TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK Aの開放待ち
 TXN1: COMMIT →LOCK Aの開放
 TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK Aの開放待ち
 TXN2: UPDATE TBL1 COL1 (排他ロック) →LOCK B
 TXN2: COMMIT →LOCK Aの開放


■WITH HOLD
カーソル処理で更新する場合にはWITH HOLDオプション付きカーソルで、
カーソルの処理中にCOMMITを発行してもカーソルがOPENのまま次のカーソルを処理できる。
→COMMIT間隔が増え、アクティブ・ログの所要量を削減できる。

以下ケースに有効。
*1つのUPDATE文で多量の更新を行うと
 1トランザクション内の更新量が非常に大きなり、
 アクティブ・ログが足りず、
 UPDATE文がSQLCODE -964で失敗する可能性が出る。


■WITH RELEASE
WITH RELEASEオプションで、分離レベルRR/RSで、カーソルのCLOSE時点に共有ロックを開放させられる。
※通常だと、カーソルをCLOSEしても、コミットまでロックは開放されない。

以下ケースに有効。
*RRやRSはロックの期間が長く、共有ロックを多く保持しなくない。
 ※分離レベルには反する動きになる。


■LOCK TABLE
LOCK TABLE文で、明示的に表ロックを獲得できる。
-IN SHARE MODEオプションで表の共有ロックを取得
-IN EXCLUSIVE MODEオプションで表の排他ロックを取得する。
LOCKは、トランザクションの終了(COMMIT/ROLLBACK)で開放される。


■省略時ロック単位の変更
ALTER TABLE LOCKSIZE ROW/TABLEで、ロック単位を変更できる。
※デフォルト:行ロック


■ロック・タイムアウト
ロック要求が許可されるまでロック要求側はロックを待つ。
ロック待ち時間が、データベース構成パラメータLOCKTIMEOUT(秒)を越すと、
ロックタイムアウトが発生して、ロック要求側に制御が戻される。
※デフォルト:無限待ち(-1)
※ロックタイムアウトしたアプリには、SQL0911N RC68が返される。
 2フェーズコミット環境では、SQL0913N RC68が返される。
※ロック待ちしてるかは、
 -LOCK SNAPSHOTモニタ
 -db2 list applications show detail
 で分かる。


■デッドロック
ロック待ちが解決しない状態。

for instance, if two process read the table, and then update the table, process A might try to get an X lock on a row on which process B has an S lock, and vice versa.

データベースマネージャ構成パラメータDLCHKTIME(ミリ秒)のサイクルで検査される。
発生すると一方のアプリにSQL0911N RC2(デッドロック検地)が返され、ロールバックされる。
※return SQL0913N REC2 in 2 phase commit.
※どちらのトランザクションがロールバックされるかは予測不可。

to avoid such deadlocks, applications that access data with the intention of modifying it should use the FOR UPDATE OF clause when performing a select.
this clause ensures that a U lock is imposed when process A attempts to read the data.


■ロックエスカレーション
1アプリが多量の行ロックでのロック用メモリの占有
を防ぐ為の縮退運転の機能。
多数の行ロックを1つの表ロックに代えてロックの量を一挙に減らす。
1つでもアプリが暴走してロックのメモリ資源を過剰に使ってしまうと、
データベース全体の傷害になるのを歯止めする仕組み。
32ビットのプラットフォームの場合、100万行のロックは72MBのメモリを使用。

□パラメータ
*LOCKLIST
 データベース構成パラメータ
 ロックリストの記憶域の量:
  4KBページ 最大524,288ページ(2GB, 32bit環境で2900万行ロック)
  @32bitプラットフォーム: 1LOCK 72BYTE
  @64bitプラットフォーム: 1LOCK 112BYTE
*MAXLOCKS (%)
 アプリがLOCKLISTの何%使ったらエスカレーションするか
 を決めるパラメータ


■ロック待機/デッドロック軽減のためのレジストリ変数
DB2_SKIPDELETED
未コミット削除(DELETE)行のスキップ指定
V8.1.4
DEFAULT: OFF
RECOMMENDED: ON
タイプ2索引でのスキャンで、削除されたキースキップするか、
を指定する。
※削除された行は表スキャンのアクセス時に無条件でスキップされる。
※タイプ2索引のスキャンでは、削除されたキーは、デフォルトはスキップされない。

□DB2_SKIPINSERTED
未コミット挿入(INSERT)行のスキップ指定
V8.2.2
DEFAULT: OFF
RECOMMENDED: ON
非コミットの挿入行を、それらが挿入されなかったかのようにスキップするか、
を指定する。

□DB2_EVALUNCOMMITED
未コミット挿入/削除/更新(UPDATE)行のスキップ指定
V8.1.4
DEFAULT: OFF
RECOMMENDED: ON
表アクセス・スキャンまたは索引アクセス・スキャンが、
非コミット・データでも述部評価を行い、
データ・レコードが述部評価を満たしていない場合行ロックを回避するか、
を指定する。


■ロック回避設定の指針
未コミット行に対して
-条件の評価を行いたい場合:
  →DB2_EVALUNCOMMITTED=ON
-条件の評価をしない
 -未コミット挿入(INSERT)行はスキップしたい場合:
   →DB2_SKIPINSERTED=ON
 -未コミット削除(DELETE)行はスキップしたい場合:
   →DB2_SKIPDELETED=ON

※DB2_SKIPINSERTED=ON, DB2_EVALUNCOMMITTED=ONを同時設定した場合、
 未コミット挿入(INSERT)行に対する動作は、
 DB2_SKIPINSERTED=ONと同じ。
※DB2_SKIPDELETED=ON, DB2_EVALUNCOMMITTED=ONを同時指定した場合、
 未コミット削除(DELETE)行に対する動作は、DB2_SKIPDELETED=ONと同じ。


■エトセトラ

□索引使わずに異なる行のUPDATEではロック待ちが発生する。
2つのアプリが索引経由で異なる行をアクセスする場合 ロック待ちは起きない。
が、索引を使わない場合は ロック待ちが発生する。


■多次元クラスタリング(Multi Demention clustering)
-複数属性のデータ・クラスタで表を構成する機能。
-次元別検索の性能向上
-データ並べ替えを目的とした再編成不要
-削除の性能向上(ブロック削除が可能)


□ALTER TABLE ... LOCKSIZE BLOCKINSERT
MDC表に対して、ブロックレベルでのロックをINSERTに対して取得する。
→同じセルに大量にINSERT処理する際の同時稼動性の向上
→取得が必要なロックの数の軽減
→ロックを取得・開放する回数軽減によるCPU負荷の低減


□DB2_MDC_ROLLOUTレジストリ変数
MDC表でセル単位でデータを削除する(ロールアウト)。
→次元列を指定してDELETEするようなケースで高速削除が可能。
→セル単位でのデータ削除で、元表へI/Oの減少
→ログの削減で、ログへのI/Oが減少


ref:
簡単シリーズ アプリケーションデザインのためのロックの基本(★★★★☆)
http://download.boulder.ibm.com/ibmdl/pub/software/dw/jp/db2/ds/techdoc/lock_v8.pdf
D-2 実践! DB2最新バージョンを使いこなそう
http://www-06.ibm.com/jp/software/data/events/db2day2005/pdf/d_2.pdf
DB2 Deadlock
http://ugya.tripod.com/deadlock/locking.htm

tag : DB2 RR RS CS UR

2009-04-13 14:15 : 開発 : コメント : 0 : トラックバック : 0 :
コメントの投稿
非公開コメント

« next  ホーム  prev »

search

ad



counter


tag cloud

category cloud