MySQLソースラーニング:MDL辞書ロック
9723 ワード
MDLとは
MDL,Meta Data lock,メタデータロック,一般に辞書ロックと呼ばれる.辞書ロックはデータロックに対応しています.ディクショナリ・ロックは、データ・オブジェクトが変更されることを保護するために使用されます.通常、いくつかのDDLは、2つのTX、TX 1がテーブルをクエリーし、TX 2がDROPを試みると、ディクショナリ・ロックがTX 2をロックし、TX 1が終了することを知っています(コミットまたはロールバック).データ・ロックは、2つのTXが同時に1行更新される場合、row lockを取得したTXが先に実行され、後者は待つしかありません.
MDLの設計目標
辞書ロックは、データベース・オブジェクトのメタデータのために設計されています.以下の3つの目的に到達する.
1.同時アクセスメモリにおけるディクショナリオブジェクトキャッシュ(table definatincache,TDC)の保護を提供する.これはシステムの内部要求です.
2.DMLの同時性を確保する.TX 1がテーブルT 1に対してクエリを行う場合、TX 2は同様にテーブルT 1に対して挿入される.
3.DMLとDDLの大部分(ALTER TABLEを除く)との反発性のようないくつかの動作の反発性を確保する.TX 1がテーブルT 1に対して挿入を実行する場合、TX 2はDROP TABLEを実行し、この2つの操作は同時化を許さないため、テーブルオブジェクトを保護する必要があり、binlogロジックの正確性を保証することができる.(以前のバージョンでは辞書ロックが文レベルでbinlogが論理的でないバグがあったようです.)
サポートされているロックのタイプ
データベース理論における基本ロックタイプはS,Xであり,意向ロックIS,IXは階層ロックのために導入されている.たとえば、テーブルのデータを変更するには、テーブルの上のテーブルレベルIXをロックしてから、変更したデータの上の行レベルXをロックします.これにより、テーブル定義を変更しようとする他のものが、テーブルレベルのXロックが取得されずに待機することを保証できます.
MySQLでは、辞書ロックのタイプを異なる文の機能に基づいてさらに細分化し、細分化の根拠は辞書の操作とデータの操作である.サブディビジョンの利点は、XとSの2つのロックのみを定義すると、互換性マトリクスの限界が必然的に生じるため、同時効率をある程度向上させることである.MySQLは、次のようなロックタイプを定義しています.
名前
意味
MDL_INTENTION_EXCLUSIVE
意向排他ロックは、範囲ロックにのみ使用されます
MDL_SHARED
データにアクセスせずに辞書オブジェクトにアクセスする共有ロック.
MDL_SHARED_HIGH_PRIO
ディクショナリオブジェクトのみにアクセス(DESC TABLEなど)
MDL_SHARED_READ
共有リードロック、selectなどのデータの読み取りに使用
MDL_SHARED_WRITE
書き込みロックを共有し、updateなどのデータを変更します.
MDL_SHARED_NO_WRITE
非書き込みロックを共有し、データの読み取りを許可し、他のTX修正データ(alter tableなど)をブロックする
MDL_SHARED_NO_READ_WRITE
辞書にアクセスするために、読み書きデータは他のTX読み書きデータを許可しない
MDL_EXCLUSIVE
辞書やデータを修正できる排他ロック
MySQLがALTER TABLEのときに他のトランザクションによるリードテーブル操作を許可していることがわかります.注意が必要なのは、読み取り操作のものはALTER TABLEでMDL_を取得する必要があることです.SHARED_NO_WRITEロック後、同時実行できません.このような応用シーンは,大きなテーブルに対してALTERを行うべきであり,他のものは依然として読むことができ,同時性が向上した.
ロックの互換性
ロックの互換性は,我々がよく見る互換性行列であり,XとSは必然的に反発し,SとSは互換性がある.MySQLは、ロックのタイプに応じて、互換性マトリクスが次のように表示されます.
IX
S
SH
SR
SW
SNW
SNRW
X
IX
1
1
1
1
1
1
1
1
S
1
1
1
1
1
1
1
0
SH
1
1
1
1
1
1
1
0
SR
1
1
1
1
1
1
0
0
SW
1
1
1
1
1
0
0
0
SNW
1
1
1
1
0
0
0
0
SNRW
1
1
1
0
0
0
0
0
X
1
0
0
0
0
0
0
0
1は互換性を表し、0は互換性を表しません.XとIXが互換性があることに気づくかもしれませんが、間違いありません.実はここのIXは伝統的な意味でのIXではありません.このIXは範囲ロックに使われているので、Xロックと反発しません.
データ構造
ロックに関連するデータ構造は主に以下のとおりです.
MDL_context:辞書ロックコンテキスト.1つの物事を含むすべての辞書ロックリクエスト.
MDL_request:ディクショナリロックリクエスト.オブジェクトに対するロックのリクエストが含まれます.
MDL_ticket:辞書ロックキュー.MDL_requestはticketを取得するためです.
MDL_lock:リソースをロックします.オブジェクトはグローバルに一意です.複数の同時可能なものを同時に得ることができる.
関連するソースファイルは主にsql/mdlである.cc
リソースのロック
ロックリソースはシステムで共有され、すなわちグローバルであり、static MDL_に格納される.map mdl_locks;のhashチェーンテーブルでは、データベース内のオブジェクトに対してhashkeyは必ず一意であり、ロックリソースに対応します.複数のトランザクションが同時に1つのテーブルに対して操作される場合、申請したlockも同じメモリオブジェクトです.mdl_の取得locksのlockはグローバル反発量によってmysql_を保護する必要があるmutex_lock(&m_mutex); m_mutexはMDL_mapのメンバー.
ロックフロー
1つのセッション接続は実装中に1つのTHDエンティティに対応し、1つのTHDは1つのMDL_に対応する.CONTEXTは、必要なmdlロックリソースを表し、MDL_CONTEXTには複数のMDL_が含まれていますREQUEST、1つのMDL_REQUESTは、1つのオブジェクトに対する何らかのタイプのlockリクエストである.各mdl_requestにはticketオブジェクトがあり、ticketにはlockが含まれています.
鍵がかかっているのはMDL_によるものですREQUESTは施錠を行います.
- Acquire_lock:
- if (mdl_request contains the needed ticket )
- return ticket;
- End if;
- Create a ticket;
- If (!find lock in lock_sys)
- Create a lock;
- End if
- If (lock can be granted to mdl_request)
- Set lock to ticket;
- Set ticket to mdl_request;
- Else
- Wait for lock
- End if
ちょっと説明すると、まずmdl_request自体は、等しいかstrongerのticketがあるかどうかを確認し、存在する場合は直接使用します.そうでなければticketを作成し、ロックオブジェクトに対応するlockを検索し、そうでなければ作成します.lockが本トランザクションに割り当てられるかどうかを確認し、直接戻ることができる場合は、このlockを待つ.
ロック待機と起動
辞書オブジェクトのロック待機は、同じオブジェクトに対して2つのものが互換性のないロックによって発生します.もちろん、lockの唯一性のため、先着先得、後着は待つしかない.
どのようにlockがgrantにTXを与えることができるかどうかを判断しますか?これはlock構造と結びつけて見る必要があります.lockには2人のメンバーがいます.grantとwait、grantはこのlockが許可しているものがどのロックをかけているかを表し、waitは待機しているトランザクションがどのロックをかけているかを示します.物事がgrantできるかどうかを判断する論理は以下の通りです.
- If(compatible(lock.grant, tx.locktype))
- If (compatible(lock.wait, tx.locktype))
- return can_grant;
- End if
- End if
すなわちgrantのロックタイプと現在のトランザクションが互換性があるかどうかをまず判断し、waitのロックタイプと現在のトランザクションが互換性があるかどうかを判断します.細心の注意を払うと、waitのロックタイプは現在のトランザクションと互換性を比較する必要はありません.これは余計なことではないでしょうか.実はそうではありません.waitの互換性マトリクスは上のマトリクスとは違いますから、waitの互換性マトリクスはDDLが待っている場合にDMLが入るのを防止しているような気がします(waitマトリクスは書かないので、コードに見てもいいです).
例:
TX1 TX2 TX3
SELECT T1
DROP T1
SELECT T1
このときTX 2はブロックされ、TX 3もブロックされ、TX 2にブロックされ、つまりwaitのイベントにブロックされ、DDLが待っている間にDMLを禁止することを保証するためかもしれません.DDLの前でDMLは確かにそんなに重要ではありませんから.
どのようにして待機している事務を呼び覚ますのでしょうか.例えばTX 2を起動し、TX 1が終了するとrelease_を呼び出すall_locks_for_name、ロックされたトランザクションを呼び出し、具体的な操作はreschedule_にカプセル化されます.waiters関数では、待機時間のタグビットをリセットして起動し、重点コードは以下の通りです.
- if (can_grant_lock(ticket->get_type(), ticket->get_ctx()))
- {
- if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))
- {
- /*
- Satisfy the found request by updating lock structures.
- It is OK to do so even after waking up the waiter since any
- session which tries to get any information about the state of
- this lock has to acquire MDL_lock::m_rwlock first and thus,
- when manages to do so, already sees an updated state of the
- MDL_lock object.
- */
- m_waiting.remove_ticket(ticket);
- m_granted.add_ticket(ticket);
- }
今日mdlシステムを全体的に見てみると、ロックの要求、待機、起動について初歩的な理解が得られました.同時性の問題は最もデバッグしにくいので、ロックの実験をしたいなら、VSデバッグの凍結スレッドの機能を利用して、同時状況制御が完全にあなたの設計の考え方に従って現れることを確保することができます.
テキストリンク:http://www.cnblogs.com/nocode/archive/2011/12/15/2289507.html