MYSQL メタデータ ロック (MDL ロック) MDL ロックの問題分析

MYSQL メタデータ ロック (MDL ロック) MDL ロックの問題分析

1. はじめに

MYSQL の MDL ロックは常に頭痛の種でした。ロックについて話すとき、通常は INNODB の下位レベルのギャップ ロック、次のキー ロック、行ロックなどを好みます。これらは理解しやすく、観察しやすいからです。しかし、MDL ロックについては観察が非常に難しいため、ほとんど知られていません。問題が発生したときに show processlist をチェックすることによってのみ確認できます。

いわゆるテーブルメタデータロックの待機などの状態は単純です。実際、MDL LOCK は MYSQL の上位層にある非常に複雑なサブシステムであり、独自のデッドロック検出メカニズムを備えています。

(無向グラフ?)そして、テーブルがロックされているかどうかというのは、実はこれを指し、その重要性と深刻さを示しています。著者も自分の必要に応じていくつか(氷山の一角)を学びました。すべてのコードを読む能力はありませんが、著者は簡単に勉強と研究ができるように、ステートメントのMDL LOCKロックプロセスを印刷するためのTICKET印刷機能を追加しました。まずは基本から始めて、何が変更されたかをお伝えします。最後に、各MDL TYPEをテストして分析します。基本的な概念や印刷機能の追加に興味がない場合は、ロックテストの第5部を直接参照できますが、基本を理解していない場合は、少し難しいように思えるかもしれません。

最近、MDL LOCK でデッドロックに遭遇しました。次の記事で事例を紹介します。ここでは理論だけを見ていきます。

----MYSQL SERVERレベルでは、実はMDL LOCKはopen_table関数で早くも取得されています。これは最も早く取得されるLOCK構造であると言えます。

---- 最も早い取得段階: THD::enter_stage: 'テーブルを開く'

コールスタックフレーム

#0 open_table_get_mdl_lock (thd=0x7fffd0000df0、ot_ctx=0x7fffec06fb00、 
  テーブルリスト=0x7fffd00067d8、フラグ=0、mdl_ticket=0x7fffec06f950)
  /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:2789 にあります
#1 open_table の 0x0000000001516e17 (thd=0x7fffd0000df0、 
  テーブルリスト=0x7fffd00067d8、ot_ctx=0x7fffec06fb00)
  /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:3237 にあります

----デッドロック検出エラーコード:

{ "ER_LOCK_DEADLOCK", 1213, "ロックを取得しようとしたときにデッドロックが見つかりました。トランザクションを再開してください" },
エラー 1213 (40001): ロックを取得しようとしたときにデッドロックが見つかりました。トランザクションを再起動してください。

MDL LOCK のデッドロック エラーは、SHOW ENGINE INNODB にデッドロック情報がない点を除いて、INNODB デッドロック エラーとまったく同じです。

----関連するコード: mdl.h mdl.cc

2. 基本的な重要なデータ構造(クラス)と概念

1. MDLタイプ

MDL_INTENTION_EXCLUSIVE(IX)

MDL_SHARED(複数可)

MDL_SHARED_HIGH_PRIO(SH)

MDL_SHARED_READ(SR)

MDL_SHARED_WRITE(SW)

MDL_SHARED_WRITE_LOW_PRIO(SWL)

MDL_SHARED_アップグレード可能 (SU)

MDL_SHARED_READ_ONLY (SRO)

MDL_SHARED_NO_WRITE(SNW)

MDL_SHARED_NO_READ_WRITE(SNRW)

MDL_EXCLUSIVE(X)

各TYPEについては後ほど詳しくテストし、ソースコードでの説明は最後に記載します。

2. MDL名前空間

MDL では、MDL_KEY は NAMESPACE+DB+OBJECT_NAME で表されます。いわゆる名前空間は重要ではありません。

以下はNAMESPACEのカテゴリです

- GLOBAL はグローバル読み取りロックに使用されます。

- TABLESPACE は表領域用です。

- SCHEMA はスキーマ (別名データベース) 用です。

- TABLE はテーブルとビュー用です。

- FUNCTION はストアド関数用です。

- PROCEDURE はストアド プロシージャ用です。

- TRIGGER はトリガー用です。

- EVENT はイベント スケジューラ イベント用です。

- COMMIT は、グローバル読み取りロックを有効にしてコミットをブロックするためのものです。

- USER_LEVEL_LOCK はユーザーレベルのロック用です。

- LOCKING_SERVICEは、名前プラグインRWロックサービス用です

3. 分類を実装する

スコープロック: 一般的にグローバルMDLロックに対応します。たとえば、読み取りロック付きのフラッシュテーブルは名前空間です: GLOBAL タイプ: S

オブジェクトロック: その名の通り、TABLEなどのオブジェクトレベルのMDLロックです。

ソースコード内のコメントは次のとおりです。

 /**
  さまざまなタイプのロックの処理方法を定義するヘルパー構造体
  特定のMDL_lockに対して。実際には、2つの戦略のみを使用します。「スコープ付き」
  GLOBAL、COMMIT、TABLESPACE、SCHEMA 名前空間のロックのロック戦略
  他のすべての名前空間には「オブジェクト」ロック戦略を使用します。
 */

4. MDL 互換性マトリックス

スコープロック:
     | アクティブの種類 |
 リクエスト | スコープロック |
  タイプ | IS(*) IX SX |
 ---------+------------------+
 です | + + + + |
 IX | + + - - |
 S | + - + - |
 バツ | + - - - |

オブジェクトロック:
    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   S | + + + + + + + + - |
   SH | + + + + + + + + - |
   SR | + + + + + + + - - |
   SW | + + + + + - - - - |
   SWLP | + + + + + - - - - |
   SU | + + + + - + - - - |
   SRO | + + + - - + + + - - |
   SNW | + + + - - - + - - - |
   SNRW | + + - - - - - - - - |
   バツ | - - - - - - - - - - - - |

5. MDLの期間とMDLの継続期間

あまり説明は要りません。ソースコードのコメントを見てください。

MDL_STATEMENT: ステートメント期間のロックは終了時に自動的に解除されます
       明細書または取引の。
MDL_TRANSACTION: トランザクション期間のロックは終了時に自動的に解除されます
        取引の
MDL_EXPLICIT: 明示的な期間を持つロックは、ステートメントとトランザクションの終了後も存続します。
       これらは、MDL_context::release_lock() を呼び出して明示的に解放する必要があります。

6. MDL LOCK 高速パス (目立たない) または低速パス (目立たない)

2 つの異なる方法を使用する目的は、MDL ロックの実装を最適化することです。以下はソース コード内のコメントです。

A) 「目立たない」ロックタイプ
      1) このセットの各タイプは、他のすべてのタイプと互換性があるはずです。
        セットからのタイプ(それ自体を含む)。
      2) これらの型はDML操作で共通であるべきである
     私たちの目標は、このロックの取得と解放を最適化することです
     m_waiting/ の複雑なチェックや操作を回避することで、
     m_grantedビットマップ/リスト。これらを、およびのチェックに置き換えます。
     整数カウンターの増分/減分。
     後者のタイプの取得/リリースを「高速パス」と呼びます。
     「高速パス」を使用すると、関連するクリティカルセクションのサイズが削減されます。
     MDL_lock::m_rwlockを使用すると、一般的なケースではロックがかかり、
     スケーラビリティ。
     特定の種類の取得/解放の量
     「目立たない」ロックはパックされたカウンタを増加/減少させます
     この関数によって MDL_lock::m_fast_path_state が返されます。
B) 「目障りな」ロックタイプ
      1) これらのタイプの許可または保留中のロックは、
        他の種類のロック、またはそれ自体と組み合わせて使用​​します。
      2) DML操作では一般的ではない
     これらのロックは常に操作を伴う取得が必要です
     m_waiting/m_granted ビットマップ/リスト、つまり「遅いパス」を使用する必要があります
     さらに、アクティブ/保留中のロックが存在する場合、
     「邪魔な」セットは「遅いパス」を使用して取得する必要があります。
     「控えめな」タイプ。

7. MDL_requestクラス

つまり、MDL LOCK要件はステートメント解析後に取得する必要があり、その後、MDL LOCKアプリケーションは、このクラスオブジェクトを介してMDLサブシステムで実行されます。このクラスオブジェクトには、おそらく次のプロパティが含まれます。

/** メタデータ ロックのタイプ。 */
 enum enum_mdl_type type; //必須タイプ/** 要求されたロックの期間。 */
 enum enum_mdl_durationduration; // 継続時間/**
  このコンテキストのロック要求のリストに参加するためのポインター。
 */
 MDL_request *next_in_list; // 二重リンクリストの実装 MDL_request **prev_in_list;
 /**
  このロック要求のロック チケット オブジェクトへのポインター。
  このロック要求が満たされた場合にのみ有効です。
 */
 MDL_ticket *ticket; // アプリケーションが成功した場合(待機なし)、実際の TICKET を指しますが、そうでない場合は NULL になります。
 /** 完全修飾名とタイプに基づいてロックが要求されます。 */
 MDL_key key; //これはMDL_KEY型であることに注意してください。主なものは上記のNAMESPACE+DB+OBJECT_NAMEです。

MDL_key クラスは、実際の NAMESPACE+DB+OBJECT_NAME であり、char 配列に格納されます。これは、MDL_LOCK および MDL_REQUEST に表示されます。

プライベート:

uint16 m_length;

uint16 m_db_name_length;

char m_ptr[MAX_MDLKEY_LENGTH]; //ここに記述

8. MDLチケット

チケットと同様に、MDL LOCKを取得した場合は、MDL_requestにチケットを返す必要があります。待つと、MDL_context::acquire_lockが取得されません。

観察することができます。もちろん、これは私が主に観察するカテゴリでもあります。

/**
  このコンテキストのロック要求のリストに参加するためのポインター。
  コンテキストはプライベートです。ここで説明されているように、コンテキスト内のリンクリストの形成はスレッドプライベートです*/
 MDL_ticket *次のコンテキスト;
 MDL_ticket **コンテキスト内の前の項目;
 /**
  満足済み/保留中のリクエストのリストに参加するためのヒント
  ロック用。外部からアクセス可能。ここで説明されているのは、MDL_LOCK のリンクリストの構成であり、これはグローバルです */
 MDL_ticket *次のロック;
 MDL_ticket **prev_in_lock;
/**
  メタデータ ロック チケットの所有者のコンテキスト。外部からアクセス可能。
  明らかに、これはチケットの所有者、つまりスレッド属性である MDL_context を指しています*/
 MDL_コンテキスト *m_ctx; 
 /**
  このロック チケットのロック オブジェクトへのポインター。外部からアクセス可能です。
  明らかにこれはMDL_LOCK*へのポインタです/
 MDL_lock *m_lock;
 /**
  チケットが「高速パス」を使用して取得されたロックに対応していることを示します
  アルゴリズム。特にこれは、
  MDL_lock::m_grantedビットマップ/リストは、代わりに
  MDL_lock::m_fast_path_locks_granted_counter
  これは、FAST PATH であるかどうかを示します。コメントから、高速パス方式は、MDL LOCK 内の許可されたビットマップとリンク リストを占有しません。代わりに、カウンター m_fast_path_locks_granted_counter が使用されます。
  こうすればコストは確実に安くなります*/
 ブール値 m_is_fast_path;
 /**
  チケットがロック要求に対応していることを示します。
  取得中にストレージエンジンに通知し、
  リリース後のストレージ エンジンの通知。
 */
 ブール値 m_hton_notified;

9. MDL_ロック

各 MDL_key は MDL_lock に対応しており、これにはいわゆる GRANTED リンク リストと WAIT リンク リストが含まれます。その複雑さを考慮すると、ソース コードのコメントを直接参照できます。これも非常に詳細です。ここで説明したいくつかのプロパティを示します。

/** 保護されているオブジェクト (データ) のキー。 */

MDL_key キー;

/** このロックに許可されたチケットのリスト。 */

チケットリストm_granted;

/** ロックの取得を待機しているコンテキストのチケット。 */

チケットリストm_waiting;

10. MDL_コンテキスト

これは、MYSQL スレッド全体が MDL ロック サブシステムと対話するための、いわゆるコンテキスト構造です。これには多くのメソッドとプロパティが含まれています。私が特に関心を持っているプロパティは次のとおりです。

/**
  ロック要求がスケジュールされたり、デッドロックによって中止された場合
  検出器の場合、結果はこのクラスに記録されます。
 */
 MDL_wait m_wait;
/**
  この接続によって取得されたすべての MDL チケットのリスト。
  これは、さまざまな MDL ロック期間のリンク リスト配列です。実際には、MDL_STATEMENTのリンクリスト、MDL_TRANSACTIONのリンクリスト、およびMDL_EXPLICITのリンクリストです*/
チケットリスト m_tickets[MDL_DURATION_END];
//これは子クラスオブジェクトを指す親クラスポインタであり、仮想関数オーバーライドの典型的な例です。実際にはスレッドを指します/*
クラス THD :public MDL_context_owner、
      パブリックQuery_arena、
      公開 Open_tables_state
*/
MDL_コンテキスト所有者 *m_owner;

11.MDL_待機

このクラスでは主に現在のチケット取得状況を扱います

enum_wait_status m_wait_status;

含む

空の初期化

許可 成功を得る

被害者デッドロック

タイムアウト

殺された殺された

12. マークを待つ

PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]=
{
 {0, "グローバル読み取りロックを待機中", 0},
 {0, "表領域メタデータのロックを待機しています", 0},
 {0, "スキーマ メタデータ ロックを待機しています", 0},
 {0, "テーブル メタデータ ロックを待機しています", 0},
 {0, "ストアド関数メタデータのロックを待機しています", 0},
 {0, "ストアド プロシージャ メタデータ ロックを待機しています", 0},
 {0, "トリガー メタデータ ロックを待機中", 0},
 {0, "イベント メタデータ ロックを待機中", 0},
 {0, "コミットロックを待機中", 0},
 {0, "ユーザーロック", 0}, /* 古いステータスと互換性を持たせます。 */
 {0, "ロック サービス ロックを待機中", 0},
 {0, "バックアップ ロックを待機中", 0},
 {0, "binlog ロックを待機中", 0}
};

3. MDL LOCK印刷機能の追加

MDL LOCK を学習する最良の方法は、MDL ロック、アップグレード、ダウングレードのプロセスを取得することです。ソースコードが大きすぎるため、すべてを網羅することは不可能です。

performance_schema.setup_consumers を更新し、 ENABLED = 'YES' に設定します。WHERE NAME = 'global_instrumentation';

performance_schema.setup_instruments を更新し、 ENABLED = 'YES' に設定します。 WHERE NAME = 'wait/lock/metadata/sql/mdl';

performance_schema.metadata_locks から * を選択します

しかし、ステートメントがどのMDLロックを取得したかを確認したい場合は、まだ無力のようです。そこで、次のように関数プロトタイプをmdl.ccに追加しました。

/*p_ticket in パラメータ*/

int my_print_ticket(const MDL_ticket* p_ticket)

また、mdl_ticketクラスでは、この関数プロトタイプがフレンド関数として追加されています。そうしないと、プライベートメンバーを取得できず、指定されたパブリックメソッドがより複雑になります。

フレンド int my_print_ticket(const MDL_ticket* p_ticket);

MDL LOCK の以下の情報は主に取得され、mysql err ログに出力されます。

スレッド ID は p_ticket->m_ctx->get_thd() を通じて取得されます。

mdl ロック データベース名は、p_ticket->m_lock->key.db_name() を通じて取得されます。

mdl ロック オブジェクト名は、p_ticket->m_lock->key.name() を通じて取得できます。

mdl ロック名前空間は、p_ticket->m_lock->key.mdl_namespace() を通じて取得されます。

mdl ロックの高速パスは、p_ticket->m_is_fast_path を通じて取得されます。取得された場合は出力され、取得されない場合は出力されません。

mdlロックタイプはp_ticket->m_typeを通じて取得されます。

mdlロック期間はp_ticket->m_durationを通じて取得されます。

出力情報は次のとおりです。

2017-08-03T07:34:21.720583Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です:

2017-08-03T07:34:21.720601Z 3 [注記] (->MDL PRINT) DB_name は:test

2017-08-03T07:34:21.720619Z 3 [注記] (-->MDL PRINT) OBJ_name は:test

2017-08-03T07:34:21.720637Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE

2017-08-03T07:34:21.720655Z 3 [注記] (---->MDL PRINT) 高速パスは: (Y)

2017-08-03T07:34:21.720673Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_WRITE(SW)

2017-08-03T07:34:21.720692Z 3 [注記] (------>MDL PRINT) Mdl の所要時間は:MDL_TRANSACTION

実際、この情報は metadata_locks の情報と似ています。これは、show processlist のスレッド ID ですが、ロック取得履歴情報を取得できます。ここでは LOCK_STATUS: GRANTED はありませんが、MDL_context::acquire_lock ロジックから判断できます。

mysql> performance_schema.metadata_locks\G から * を選択します
************************** 1. 行 ****************************
オブジェクトタイプ: テーブル
OBJECT_SCHEMA: テスト
オブジェクト名: テスト
オブジェクトインスタンスの開始: 140734412907760
ロックタイプ: 共有書き込み
LOCK_DURATION: トランザクション
LOCK_STATUS: 許可
ソース: sql_parse.cc:6314
所有者スレッドID: 39
オーナーイベントID: 241

4. 観察に適した場所に印刷機能を追加する

MDL LOCK のロック、アップグレード、ダウングレードを研究したいので、それらの関数エントリを見つけて、適切な位置に印刷機能を追加して観察する必要があります。印刷位置は以下にマークされており、ソースコードの大部分は削除されています。参考としてソースコードを確認してください。

1. ロック: MDL_context::acquire_lock

ブール
MDL_context::acquire_lock(MDL_request *mdl_request、ulong lock_wait_timeout) を取得します。
{
 if (mdl_request->ticket) //チケットを正常に取得
 {
  /*
   待たずにロックを取得することができました。
   MDL_lock、MDL_context、MDL_requestが更新されました
   したがって、単純に成功を返すことができます。
  */
  //REQUESET は TICKET を正常に取得し、ここで FALSE を返します。
 }
 /*
  待機せずにロックを取得しようとしましたが失敗しました。
  この試みの結果、m_lock付きのMDL_ticketが取得されました
  対応するMDL_lockオブジェクトを指すメンバー。
  MDL_lock::m_rwlock が書き込みロックされています。
 */
 //取得に失敗しました。MDL_lock 待機キューに参加します。lock= ticket->m_lock;
 ロック->m_waiting.add_ticket(チケット);
 will_wait_for(ticket); //デッドロック検出/* オブジェクトに共有ロックまたは排他ロックがあります。 */
 DEBUG_SYNC(get_thd(), "mdl_acquire_lock_wait");
 デッドロックを見つける(); 
 //ここでTICKETを印刷し、待機プロセスに入ります if (lock->needs_notification(ticket) || lock->needs_connection_check())
 {
  }
 done_waiting_for(); //デッドロック検出待機グラフが調整されるのを待ち、待機エッジ(無向グラフ)を削除します。
 //もちろん、ここでは待機後に成功し、ステータスは GRANTED です
 DBUG_ASSERT(wait_status == MDL_wait::GRANTED);
 m_tickets[mdl_request->duration].push_front(チケット);
 mdl_request->ticket = チケット;
 mysql_mdl_set_status(チケット->m_psi、MDL_ticket::GRANTED);
 //ここではREQUESTを待って取得したTICKETを出力します
 FALSE を返します。
}

2. ダウングレード: void MDL_ticket::downgrade_lock(enum_mdl_type new_type)

void MDL_ticket::downgrade_lock(enum_mdl_type new_type)
{
 /* EXCLUSIVE および SHARED_NO_WRITE からのダウングレードのみを許可します。 */
 DBUG_ASSERT(m_type == MDL_EXCLUSIVE ||
       m_type == MDL_SHARED_NO_WRITE);
//ダウングレード前にTICKETを印刷してください
 (m_hton_notified) の場合
 {
  mysql_mdl_set_status(m_psi、MDL_ticket::POST_RELEASE_NOTIFY);
  m_ctx->get_owner()->notify_hton_post_release_exclusive(&m_lock->key);
  m_hton_notified = false;
  mysql_mdl_set_status(m_psi、MDL_ticket::GRANTED);
 }
//関数の最後では、ダウングレードされたTICKETを発行することを約束します
}

3. アップグレード: MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,enum_mdl_type new_type, ulong lock_wait_timeout)

ブール
MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
                 enum_mdl_type 新しいタイプ、
                 ulong ロック待ちタイムアウト)
{
 MDL_REQUEST_INIT_BY_KEY(&mdl_new_lock_request,
             &mdl_ticket->m_lock->キー、新しいタイプ、
             MDL_TRANSACTION); //リクエストを構築する
 //ここにTICKETタイプが印刷されます if (acquire_lock(&mdl_new_lock_request, lock_wait_timeout)) //新しいLOCK_TYPEでロックを試みます DBUG_RETURN(TRUE);
 is_new_ticket = ! has_lock(mdl_svp、mdl_new_lock_request.ticket);
 ロック = mdl_ticket->m_lock;
 //以下は、MDL_LOCK の一連のメンテナンスと、いわゆるマージ操作です/* 以下のコードでは、「目障りな」タイプのロックにアップグレードしていることを前提としています。 */
 DBUG_ASSERT(lock->is_obtrusive_lock(new_type));
 /* 取得したロックと元のロックをマージします。@todo: メソッドに移動します。 */
 mysql_prlock_wrlock(&lock->m_rwlock);
 (新しいチケットの場合)
 {
  m_tickets[MDL_TRANSACTION].remove(mdl_new_lock_request.ticket);
  MDL_ticket::destroy(mdl_new_lock_request.ticket);
 }
 //アップグレードされた TICKET タイプがここに出力されます DBUG_RETURN(FALSE);
}

もちろん、今はこれらの場所でしか印刷していません。必要に応じて、将来的に他の場所にも機能を追加できます。

5. 各種MDLロックタイプロックテスト

1. MDL_INTENTION_EXCLUSIVE (IX)

このロックは多くの操作で発生します。たとえば、DML/DDL 操作を実行するときにトリガーされます。実際、DELETE/UPDATE/INSERT/FOR UPDATE などの DML 操作は、GLOBAL に IX ロックを追加してからオブジェクトをロックします。DDL ステートメントは、少なくとも GLOBAL に IX ロックを追加し、オブジェクトが属する SCHEMA に IX ロックを追加します。このオブジェクトのロックは、DELETE によってトリガーされる GLOABL IX MDL LOCK です。

2017-08-03T18:22:38.092100Z 3 [注記] Test2:open_tables_for_query()
2017-08-03T18:22:38.092205Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T18:22:38.092242Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T18:22:38.092276Z 3 [注記] (--->MDL PRINT) 名前空間は:GLOBAL 
2017-08-03T18:22:38.092310Z 3 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T18:22:38.092344Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_INTENTION_EXCLUSIVE(IX) 
2017-08-03T18:22:38.092380Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_STATEMENT 
2017-08-03T18:22:38.092551Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 

以下は、ALETERステートメントによってトリガーされるGLOABLIX MDL LOCKとSCHEMAレベルのMDL LOCKです。

2017-08-03T18:46:05.894871Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T18:46:05.894915Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T18:46:05.894948Z 3 [注記] (--->MDL PRINT) 名前空間は:GLOBAL 
2017-08-03T18:46:05.894980Z 3 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T18:46:05.895012Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_INTENTION_EXCLUSIVE(IX) 
2017-08-03T18:46:05.895044Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_STATEMENT 
2017-08-03T18:46:05.895076Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T18:46:05.895116Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T18:46:05.895147Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T18:46:05.895206Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T18:46:05.895243Z 3 [注記] (-->MDL PRINT) OBJ_name は次のとおりです: 
2017-08-03T18:46:05.895276Z 3 [注記] (--->MDL PRINT) 名前空間は:SCHEMA 
2017-08-03T18:46:05.895325Z 3 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T18:46:05.895357Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_INTENTION_EXCLUSIVE(IX) 
2017-08-03T18:46:05.895390Z 3 [注記] (------>MDL PRINT) Mdl の所要時間は:MDL_TRANSACTION 
2017-08-03T18:46:05.895421Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

つまり、この MDL LOCK はどこにでもあり、唯一の問題は互換性があるかどうかです。互換性がない場合は、ブロックされます。 SCOPEDのIX型は、以下の例外に遭遇しない限り、一般的に互換性があります。
Sタイプ

2. MDL_SHARED(S)

このロックは、通常、読み取りロック付きのフラッシュテーブルで使用されます。

mysql> 読み取りロック付きのテーブルをフラッシュします。
クエリは正常、影響を受けた行は 0 行 (0.01 秒)
2017-08-03T18:19:11.603911Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T18:19:11.603947Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T18:19:11.603971Z 3 [注記] (--->MDL PRINT) 名前空間は:GLOBAL 
2017-08-03T18:19:11.603994Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED(S) です 
2017-08-03T18:19:11.604045Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_EXPLICIT 
2017-08-03T18:19:11.604073Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T18:19:11.604133Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T18:19:11.604156Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T18:19:11.604194Z 3 [注記] (--->MDL PRINT) 名前空間は:COMMIT 
2017-08-03T18:19:11.604217Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED(S) です 
2017-08-03T18:19:11.604240Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_EXPLICIT 
2017-08-03T18:19:11.604310Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 

名前空間はGLOBALで、COMMITは明らかにSCOPED LOCKであり、TYPEはSであることに気づく。したがって、互換性原則によれば、
SCOPED の MDL IX は MDL S と互換性がありません。読み取りロックを使用してテーブルをフラッシュすると、すべての DELTE/UPDATE/INSERT/FOR UPDATE 操作がブロックされます。
DMLおよびDDL操作など(これらの操作にはGLOBAL MDL IXロックが必要であるため)

3. MDL_SHARED_HIGH_PRIO (SH)

このロックは基本的に誰もが頻繁に使用しますが、あまり意識しません。たとえば、私たちは通常desc操作を使用します

互換性:

    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SH | + + + + + + + + - |
mysql> desc test.testsort10;

2017-08-03T19:06:05.843277Z 4 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T19:06:05.843324Z 4 [注記] (>MDL PRINT) スレッド ID は 4 です: 
2017-08-03T19:06:05.843359Z 4 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:06:05.843392Z 4 [注記] (-->MDL PRINT) OBJ_name は:testsort10 
2017-08-03T19:06:05.843425Z 4 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:06:05.843456Z 4 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T19:06:05.843506Z 4 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_HIGH_PRIO(SH) 
2017-08-03T19:06:05.843538Z 4 [注記] (------>MDL PRINT) Mdl の所要時間は:MDL_TRANSACTION 
2017-08-03T19:06:05.843570Z 4 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

このタイプは優先度が高くなりますが、X とは互換性がありません。たとえば、名前変更フェーズでは desc 操作を実行できないことも簡単に理解できます。

4. MDL_SHARED_READ(SR)

このロックは通常、非現在の読み取り選択での互換性のために使用されます。

    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SR | + + + + + + + - - |
mysql> test.testsort10 から * を選択し、制限 1 にします。

2017-08-03T19:13:52.338764Z 4 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T19:13:52.338813Z 4 [注記] (>MDL PRINT) スレッド ID は 4 です: 
2017-08-03T19:13:52.338847Z 4 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:13:52.338883Z 4 [注記] (-->MDL PRINT) OBJ_name は:testsort10 
2017-08-03T19:13:52.338917Z 4 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:13:52.338950Z 4 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T19:13:52.339025Z 4 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_READ(SR) 
2017-08-03T19:13:52.339062Z 4 [注記] (------>MDL PRINT) Mdl の所要時間は:MDL_TRANSACTION 
2017-08-03T19:13:52.339097Z 4 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

ここで、選択がブロックされる状況に時々遭遇することがあるということにまだ言及しておく必要があります (たとえば、DDL の特定の段階でオブジェクト MDL X ロックが必要な場合など)。文句を言わなければならない
MYSQL は実際に select をブロックします。実際、これはオブジェクト mdl lock X と SR 間の非互換性の問題です (前の互換性マトリックスを参照)。

5. MDL_SHARED_WRITE(SW)

このロックは通常、DDL 操作を除く、DELETE/UPDATE/INSERT/FOR UPDATE 操作のテーブル (現在読み取られている) をロックするために使用されます。ただし、DML 操作には実際には GLOBAL IX ロックがあることに注意してください。前述のように、このロックはオブジェクトに対してのみ適用されます。

互換性:

    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SW | + + + + + - - - - |
mysql> test.testsort10 から * を選択して、更新の制限を 1 にします。

2017-08-03T19:25:41.218428Z 4 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T19:25:41.218461Z 4 [注記] (>MDL PRINT) スレッドIDは4です: 
2017-08-03T19:25:41.218493Z 4 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:25:41.218525Z 4 [注記] (-->MDL PRINT) OBJ_name は:testsort10 
2017-08-03T19:25:41.218557Z 4 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:25:41.218588Z 4 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T19:25:41.218620Z 4 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_WRITE(SW) 
2017-08-03T19:25:41.218677Z 4 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T19:25:41.218874Z 4 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

6. MDL_SHARED_WRITE_LOW_PRIO (SWL)

このロックはほとんど使用されません。ソースコードのコメントのみ

DML文で変更に使用される

テーブルとLOW_PRIORITY句の使用

使用します

互換性:

    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SWLP | + + + + + - - - - |
mysql> LOW_PRIORITY を更新 test.testsort10 id1=1000 に設定、id1= 96282;
2017-08-03T19:32:47.433507Z 4 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T19:32:47.433521Z 4 [注記] (>MDL PRINT) スレッド ID は 4 です: 
2017-08-03T19:32:47.433533Z 4 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:32:47.433547Z 4 [注記] (-->MDL PRINT) OBJ_name は:testsort10 
2017-08-03T19:32:47.433560Z 4 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:32:47.433572Z 4 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T19:32:47.433594Z 4 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_WRITE_LOW_PRIO(SWL) 
2017-08-03T19:32:47.433607Z 4 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T19:32:47.433620Z 4 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

7. MDL_SHARED_UPGRADABLE (SU)

このロックは通常、ALTER TABLE ステートメントで使用されます。SNW、SNRW、X にアップグレードでき、少なくとも X ロックは SU にダウングレードできます。

実際、INNODB ONLINE DDLはこれに大きく依存しており、DML(SW)とSELECT(SR)はブロックされません。

互換性:

    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SU | + + + + - + - - - |

互換性を検討する必要があります。OBJECT LOCK では、(SELECT)SR (DML)SW がすべて許可されていることがわかります。SCOPED LOCK では、DML DDL が GLOBAL でロックされますが、そのタイプはすべて IX です。したがって、この SU ロックは、DML/SELECT 読み取りおよび書き込み操作が INNODB エンジン レイヤーに入ることをブロックしません。これは、ONLINE DDL の基礎です。互換性がない場合は、ONLINE DDL はおろか、INNODB エンジン レイヤーに入ることはできません。ALGORITHM=INPLACE と述べ、LOCK を設定していないことに注意してください。

(LOCK=DEFAULTまたはLOCK句を省略したDDL操作の場合、MySQLは最低レベルの
この種の操作に利用可能なロックの数。これにより、同時クエリ、DML、またはその両方をどこでも実行できます。
これは、事前に計画され、事前にテストされた変更が、
そのテーブルのワークロードに基づいて可用性の問題が発生する
主キーに対する操作でALGORITHM=INPLACEを使用すると、データはコピーされるものの、
ALGORITHM=COPY を使用するよりも効率的です。その理由は次のとおりです。
? ALGORITHM=INPLACEの場合、UNDOログや関連するREDOログは必要ありません。これらの操作により、
ALGORITHM=COPY を使用する DDL ステートメントへのオーバーヘッド。
? セカンダリ インデックス エントリは事前にソートされているため、順番にロードできます。
? セカンダリ インデックスへのランダム アクセス挿入がないため、変更バッファは使用されません。

例えば次のような文

mysql> alter table testsort12 に列 it int not null を追加します。
クエリは正常、影響を受けた行は 0 行 (6.27 秒)
レコード: 0 重複: 0 警告: 0

簡単に分析してみましょう:

2017-08-03T19:46:54.781453Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T19:46:54.781487Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T19:46:54.781948Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:46:54.781990Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T19:46:54.782026Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:46:54.782060Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_UPGRADABLE(SU) 
2017-08-03T19:46:54.782096Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T19:46:54.782175Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T19:46:54.803898Z 3 [注記] (upgrade_shared_lock)このMDLロックはアップグレードされます
2017-08-03T19:46:54.804201Z 3 [注記] (upgrade_shared_lock)このMDLロックは
2017-08-03T19:46:54.804240Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T19:46:54.804254Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:46:54.804267Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T19:46:54.804280Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:46:54.804293Z 3 [注記] (----->MDL PRINT) Mdl タイプ:MDL_EXCLUSIVE(X) 
2017-08-03T19:46:54.804306Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T19:46:54.804319Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T19:46:54.855563Z 3 [注] (downgrade_lock)このMDLロックはダウングレードします
2017-08-03T19:46:54.855693Z 3 [注記] (downgrade_lock) このMDLロックへ
2017-08-03T19:46:54.855706Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T19:46:54.855717Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:46:54.856053Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T19:46:54.856069Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:46:54.856082Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_UPGRADABLE(SU) 
2017-08-03T19:46:54.856094Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T19:46:54.856214Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T19:47:00.260166Z 3 [注記] (upgrade_shared_lock)このMDLロックはアップグレードされます
2017-08-03T19:47:00.304057Z 3 [注記] (upgrade_shared_lock)このMDLロックは
2017-08-03T19:47:00.304090Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T19:47:00.304105Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:47:00.304119Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T19:47:00.304132Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:47:00.304181Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_EXCLUSIVE(X) 
2017-08-03T19:47:00.304196Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T19:47:00.304211Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T19:47:01.032329Z 3 [注記] (acquire_lock)このMDLロックは取得できました! 

まず、testsort12テーブルを取得します

2017-08-03T19:46:54.781487 MDL_SHARED_UPGRADABLE (SU) を取得しました
2017-08-03T19:46:54.804293 MDL_EXCLUSIVE(X) をアップグレード 
2017-08-03T19:46:54.855563 ダウングレード MDL_SHARED_UPGRADABLE (SU)
2017-08-03T19:47:00.304057 MDL_EXCLUSIVE(X) のアップグレード 

なぜなら、この変更操作は、とにかく時間がかかります。ダウングレードが完了した 2017-08-03T19:46:54 から 2017-08-03T19:47:00 までの時間が、実際に最も時間がかかっていることがわかります。実際、これが実際の COPY 操作ですが、このプロセスは実際には MDL SU モードであるため、DML/SELECT 操作はブロックされません。
ここで、いわゆる ONLINE DDL は、COPY フェーズ中に DML/SELECT 操作をブロックしないだけであることに注意してください。データベースの負荷が軽いときに実行するのが最適です。
たとえば、DML が送信されなかったり、SELECT が完了しなかったりすると、SW SR は X をブロックし、X はすべてをブロックすることができ、優先度が高くなります。これによって発生する現象は、DML が送信されないため DDL 操作がブロックされ、DDL 操作によってすべての操作がブロックされ、基本的にこのテーブルに対するすべての操作がブロックされるというものです。 ALGORITHM=COPY の場合、コードの残りの部分は同様ですが、COPY フェーズで SNW ロックが使用されます。次に、まず SNW ロックについて説明します。

8. MDL_SHARED_NO_WRITE (SNW)

前述のように、データの一貫性を保護するために ALGORITHM=COPY で使用するために、SU を SNW にアップグレードし、SNW を X にアップグレードできます。
まずは互換性を確認しましょう

   リクエスト | ロックのリクエストを許可しました          
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SNW | + + + - - - + - - - |

SR は動作しますが、SW は動作しないことがわかります。もちろん、DML (SW) はブロックされますが、SELECT (SR) はブロックされません。以下に重要な部分のみを示します。

mysql> テーブル testsort12 を変更し、列 ik int not null を追加します。ALGORITHM=COPY;
2017-08-03T20:07:58.413215Z 3 [注記] (upgrade_shared_lock)このMDLロックは
2017-08-03T20:07:58.413241Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T20:07:58.413257Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T20:07:58.413273Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T20:07:58.413292Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T20:07:58.413308Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_NO_WRITE(SNW) 
2017-08-03T20:07:58.413325Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T20:07:58.413341Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T20:08:25.392006Z 3 [注記] (upgrade_shared_lock)このMDLロックは
2017-08-03T20:08:25.392024Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T20:08:25.392086Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T20:08:25.392159Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T20:08:25.392199Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T20:08:25.392214Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_EXCLUSIVE(X) 
2017-08-03T20:08:25.392228Z 3 [注記] (------>MDL PRINT) Mdl の所要時間は:MDL_TRANSACTION 
2017-08-03T20:08:25.392242Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T20:07:58.413308 MDL_SHARED_NO_WRITE (SNW) を取得しました 
2017-08-03T20:08:25.392006 MDL_EXCLUSIVE(X) にアップグレード

2017-08-03T20:07:58.413308 から 2017-08-03T20:08:25.392006 までの時間が実際の COPY 時間です。COPY 期間全体を通じて DML のみが実行可能であることがわかります。
SELECT ができないことも、ALGORITHM=COPY と ALGORITHM=INPLACE の主な違いです。

9. MDL_SHARED_READ_ONLY (SRO)

LOCK TABLES READ文の場合

互換性は次のとおりです

    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SRO | + + + - - + + + - - |
DML (SW) はブロックされますが、SELECT (SR) は引き続き可能です。
mysql> テーブル testsort12 を読み取りロックします。
クエリは正常、影響を受けた行は 0 行 (0.01 秒)
2017-08-03T21:08:27.267947Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T21:08:27.267979Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T21:08:27.268009Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T21:08:27.268040Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T21:08:27.268070Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T21:08:27.268113Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_READ_ONLY(SRO) 
2017-08-03T21:08:27.268145Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T21:08:27.268175Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

10. MDL_SHARED_NO_READ_WRITE (SNRW)

LOCK TABLES WRITE文の場合

互換性:

    リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   SNRW | + + - - - - - - - - |

DML (SW) と SELECT (SR) がブロックされ、SH のみがまだ使用可能であり、DESC (SH) も使用可能であることがわかります。

mysql> テーブル testsort12 の書き込みをロックします。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)
2017-08-03T21:13:07.113347Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T21:13:07.113407Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T21:13:07.113435Z 3 [注記] (--->MDL PRINT) 名前空間は:GLOBAL 
2017-08-03T21:13:07.113458Z 3 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T21:13:07.113482Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_INTENTION_EXCLUSIVE(IX) 
2017-08-03T21:13:07.113505Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_STATEMENT 
2017-08-03T21:13:07.113604Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T21:13:07.113637Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T21:13:07.113660Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T21:13:07.113681Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T21:13:07.113703Z 3 [注記] (-->MDL PRINT) OBJ_name は次のとおりです: 
2017-08-03T21:13:07.113725Z 3 [注記] (--->MDL PRINT) 名前空間は:SCHEMA 
2017-08-03T21:13:07.113746Z 3 [注記] (---->MDL PRINT) 高速パスは: (Y)
2017-08-03T21:13:07.113768Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_INTENTION_EXCLUSIVE(IX) 
2017-08-03T21:13:07.113791Z 3 [注記] (------>MDL PRINT) Mdl の所要時間は:MDL_TRANSACTION 
2017-08-03T21:13:07.113813Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY 
2017-08-03T21:13:07.113842Z 3 [注記] (acquire_lock)このMDLロックは取得できました!
2017-08-03T21:13:07.113865Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T21:13:07.113887Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T21:13:07.113922Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T21:13:07.113945Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T21:13:07.113975Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_SHARED_NO_READ_WRITE(SNRW) 
2017-08-03T21:13:07.113998Z 3 [注記] (------>MDL PRINT) Mdl の所要時間は:MDL_TRANSACTION 
2017-08-03T21:13:07.114021Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

さらに、ロックテーブルはGLOBALとSCHEMAのIXロックも必要とします。言い換えれば、読み取りロック付きのフラッシュテーブルはブロックされます。
lock table testsort12 書き込み。ただし、lock table testsort12 読み取りはブロックされません。

11. MDL_EXCLUSIVE(X)

CREATE/DROP/RENAME TABLE 操作として注釈が付けられたさまざまな DDL 操作に使用されます。実際、上で分析したように、ほとんどすべての DDL 操作にはこのロックが関係します。
列追加操作ですが、所要時間は通常短くなります。

互換性:

   リクエスト | ロックのリクエストを許可しました |
    タイプ | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+--------------------------------------------+
   バツ | - - - - - - - - - - - - |

すべてをブロックする事故はないが、すべてによってブロックされることもある。

例えば、先ほどの列追加操作

2017-08-03T19:46:54.804240Z 3 [注記] (>MDL PRINT) スレッド ID は 3 です: 
2017-08-03T19:46:54.804254Z 3 [注記] (->MDL PRINT) DB_name は:test 
2017-08-03T19:46:54.804267Z 3 [注記] (-->MDL PRINT) OBJ_name は:testsort12 
2017-08-03T19:46:54.804280Z 3 [注記] (--->MDL PRINT) 名前空間は:TABLE 
2017-08-03T19:46:54.804293Z 3 [注記] (----->MDL PRINT) Mdl タイプは:MDL_EXCLUSIVE(X) 
2017-08-03T19:46:54.804306Z 3 [注記] (------>MDL PRINT) Mdl 期間は:MDL_TRANSACTION 
2017-08-03T19:46:54.804319Z 3 [注記] (------->MDL PRINT) Mdl ステータスは:EMPTY

6. ソースコードコメント

列挙型 enum_mdl_type {
 /*
  意図的な排他メタデータ ロック。スコープ ロックにのみ使用されます。
  このタイプのロックの所有者は、アップグレード可能な排他ロックを取得できます。
  個々のオブジェクト。
  他のIXロックと互換性があるが、スコープ付きSおよび
  Xロック。
 */
 MDL_INTENTION_EXCLUSIVE = 0、
 /*
  共有メタデータ ロック。
  オブジェクトのメタデータのみに関心がある場合に使用します
  オブジェクトデータにアクセスする意図はありません(例:保存された
  ルーチン内または準備済みステートメントの準備中)。
  このタイプのロックは、オープンハンドラーにも誤って使用されます。ロック
  このステートメントによって取得されたロックは、取得されたロックと互換性がある必要があります
  LOCK TABLES ... WRITE文、つまりSNRW(では
  HANDLER ... OPEN時にSロックを取得し、SRにアップグレードする
  ハンドラのロック...必要な問題は解決されないので読みます
  テーブルレベルのロックを待機しているDML文を中止するには
  同じ接続で HANDLER を開きます。
  SNRWロックをアップグレードする際に発生する可能性のあるデッドロックを回避するために
  アクティブなSロックが所有されているテーブルに対するXロック
  スレッドが所有するテーブルレベルのロックを順番に待機するスレッド
  アップグレードを実行するには、thr_abort_locks_for_thread()を使用する必要があります。
  このような状況にある施設。
  この問題は、ストアドルーチンのロックでは発生しません。
  SNRWロックを使用してください。Sロックを使用する場合も発生しません。
  PREPARE呼び出し中にテーブルレベルのロックが取得されないため
  場合。
 */
 MDL_SHARED、
 /*
  優先度の高い共有メタデータ ロック。
  オブジェクトデータにアクセスする意図がない場合(つまり、
  (表内のデータ)
  「高優先度」とは、他の共有ロックとは異なり、
  保留中の排他ロック要求を無視します。
  データではなくメタデータのみにアクセスする必要がある場合、例えば、
  INFORMATION_SCHEMA テーブルに入力します。
  SHロックはSNRWロックと互換性があるため、
  SHロックを保持しているロックは、いかなる種類のテーブルレベルのロックも取得しようとしない。
  または行レベルのロックはデッドロックにつながる可能性があるため、
  SHロックを取得すると、接続は他のロックを待つ必要がなくなります。
  リソース不足を引き起こす可能性があるため、Xロックの枯渇と潜在的な
  SNWまたはSNRWをXロックにアップグレード中にデッドロックが発生する(例:
  アップグレード接続は待機中のリソースを保持します。
 */
 MDL_SHARED_HIGH_PRIO、
 /*
  データを読み取る意図がある場合のための共有メタデータロック
  表から。
  この種類のロックを保持している接続は、テーブルのメタデータを読み取り、
  テーブル データ (適切なテーブルおよび行レベルのロックを取得した後)。
  つまり、TL_READ、TL_READ_NO_INSERT、および
  テーブルに SR MDL ロックが保持されている場合、テーブルに対して同様のテーブル レベルのロックが適用されます。
  SELECT、サブクエリ、および LOCK TABLE 内のテーブルに使用されます...READ
  声明。
 */
 MDL_SHARED_READ、
 /*
  変更の意図がある場合のための共有メタデータロック
  テーブル内のデータを(単に読み取るだけでなく)表示します。
  SWロックを保持している接続は、テーブルメタデータを読み取り、変更したり、読み取ったりすることができます。
  テーブル データ (適切なテーブルおよび行レベルのロックを取得した後)。
  INSERT、UPDATE、DELETEによって変更されるテーブルに使用されます
  ステートメントは実行できますが、LOCK TABLE ... WRITEまたはDDLは実行できません。
  更新するには...を選択します。
 */
 MDL_SHARED_WRITE、
 /*
  MDL_SHARED_WRITEロックの優先度が低いバージョン。
  MDL_SHARED_READ_ONLYロック。DML文で変更に使用される。
  テーブルと LOW_PRIORITY 句を使用します。
 */
 MDL_SHARED_WRITE_LOW_PRIO、
 /*
  同時更新と
  テーブルデータの読み取り。
  この種類のロックを保持している接続は、テーブルのメタデータを読み取り、
  テーブルデータ。このロックは互換性があるため、データを変更しないでください。
  SROロック。
  SNW、SNRW、Xロックにアップグレードできます。SUロックをXにアップグレードすると
  または SNRW ロック データの変更が自由に発生する可能性があります。
  ALTER TABLE の最初のフェーズで使用されます。
 */
 MDL_SHARED_UPGRADABLE、
 /*
  テーブルからデータを読み取る必要がある場合のための共有メタデータロック
  データとメタデータの両方に対するすべての同時変更をブロックします。
  LOCK TABLES READ ステートメントによって使用されます。
 */
 MDL_SHARED_READ_ONLY、
 /*
  アップグレード可能な共有メタデータロックは、更新の試みをすべてブロックします。
  テーブルデータの読み取りを許可します。
  この種類のロックを保持している接続は、テーブルのメタデータを読み取り、
  テーブルデータ。
  X メタデータ ロックにアップグレードできます。
  このタイプのロックはSNRWまたはSWと互換性がないので注意してください。
  ロックの種類、読み取り用の適切なエンジンレベルのロックを取得する
  (MyISAMの場合はTL_READ*、InnoDBの場合は共有行ロック)
  競合なし。
  ALTER TABLEの最初のフェーズで、データをコピーするときに使用します。
  テーブルからの同時 SELECT は許可しますが、UPDATE は許可しません。
 */
 MDL_SHARED_NO_WRITE、
 /*
  他の接続を可能にするアップグレード可能な共有メタデータロック
  テーブルのメタデータにはアクセスできますが、データにはアクセスできません。
  テーブルデータの読み取りや更新の試みをすべてブロックし、
  INFORMATION_SCHEMA および SHOW クエリ。
  この種類のロックを保持している接続は、テーブルメタデータの読み取り、変更、
  テーブルデータを読み取ります。
  X メタデータ ロックにアップグレードできます。
  LOCK TABLES WRITE ステートメントに使用されます。
  S および SH 以外のロック タイプとは互換性がありません。
 */
 MDL_SHARED_NO_READ_WRITE、
 /*
  排他的なメタデータ ロック。
  このロックを保持している接続は、テーブルのメタデータとデータの両方を変更できます。
  このロックが保持されている間は、他のタイプのメタデータ ロックを許可することはできません。
  CREATE/DROP/RENAME TABLE文および実行に使用します。
  他の DDL ステートメントの特定のフェーズ。
 */
 MDL_EXCLUSIVE、
 /* これで最後です!!! */
 MDL_TYPE_END};
/** メタデータ ロックの期間。 */
列挙型 enum_mdl_duration {
 /**
  ステートメント期間のロックは終了時に自動的に解除されます
  明細書または取引の。
 */
 MDL_ステートメント = 0、
 /**
  トランザクション期間のロックは終了時に自動的に解除されます
  取引の。
 */
 MDL_TRANSACTION、
 /**
  明示的な期間を持つロックは、ステートメントとトランザクションの終了後も存続します。
  これらは、MDL_context::release_lock() を呼び出して明示的に解放する必要があります。
 */
 MDL_EXPLICIT、
 /* これで最後です! */
 終了日時:
/**
  オブジェクトの名前空間。
  Sic: この列挙型に新しいメンバーを追加するときは、必ず
  mdl 内の m_namespace_to_wait_state_name 配列を更新します。
  異なる名前空間には異なるタイプのオブジェクトが存在する
   - GLOBAL はグローバル読み取りロックに使用されます。
   - TABLESPACE は表領域用です。
   - SCHEMA はスキーマ (別名データベース) 用です。
   - TABLE はテーブルとビュー用です。
   - FUNCTION はストアド関数用です。
   - PROCEDURE はストアド プロシージャ用です。
   - TRIGGER はトリガー用です。
   - EVENT はイベント スケジューラ イベント用です。
   - COMMIT は、グローバル読み取りロックを有効にしてコミットをブロックするためのものです。
   - USER_LEVEL_LOCK はユーザーレベルのロック用です。
   - LOCKING_SERVICEは、名前プラグインRWロックサービス用です
  トリガーにはメタデータロックはありませんが、
  それらには別の名前空間が必要です。
  MDL_key は MDL サブシステムの外部でも使用されます。
  また、ユーザーレベルのロックを待つリクエストは特別なものになることに注意してください。
  クライアントとの接続が失われた場合、処理待機は中止されます。
 */
 enum enum_mdl_namespace { GLOBAL=0,
              テーブルスペース、
              スキーマ、
              テーブル、
              関数、
              手順、
              トリガー、
              イベント、
              専念、
              USER_LEVEL_LOCK、
              ロックサービス、
              バックアップ、
              ビンログ、
              /* これで最後です! */
              名前空間_END };

以下もご興味があるかもしれません:
  • MySQL でテーブル メタデータ ロックを待機する理由と方法
  • MySQLのテーブル構造を変更する際に知っておきたいメタデータロックの詳しい解説
  • MySQLスレーブは列の外部キーチェックと自動増分ロックを遅延します
  • MySQLのネクストキーロックのロック範囲についての簡単な説明
  • MySQL ロック制御同時実行方法
  • PHP+MySQL の高同時ロックトランザクション処理問題の解決方法
  • MYSQL メタデータ ロック (MDL ロック) の理論とロック タイプ テスト

<<:  Linux で JDK 環境を構成する方法

>>:  Windows サーバー ファイルをローカルにバックアップする方法、Windows サーバー データ バックアップ ソリューション

推薦する

Vueは小さなメモ帳機能を実装しました

この記事の例では、メモ帳の小さな機能を実現するためのvueの具体的なコードを参考までに共有しています...

Vue バックエンド管理システムのページング機能の実装例

この記事では、主に Vue バックグラウンド管理システムのページング機能の実装を紹介し、次のように共...

React Routerの歴史について簡単に説明します

React Router を理解したいなら、まず歴史を理解する必要があります。より具体的には、Rea...

MySql における特殊演算子の使用の概要

序文MySQL には次の 4 種類の演算子があります。算術演算子比較演算子論理演算子ビット演算子これ...

Tomcatのサーバーオプションの詳細な説明

1. 構成デフォルトでは、最初の 2 つはチェックされていないので、チェックする必要があります。 (...

Mysql Workbench クエリ mysql データベース メソッド

Mysql Workbench はオープンソースのデータベース クライアントです。このオープンソース...

JavaScriptの詳細な分析と方向の変更方法

目次これ方法オブジェクト内これを隠した厳密モードこれを変更してこれいつものように、まずはコードを見て...

HTML チュートリアル: よく使われる HTML タグのコレクション (6)

関連記事:初心者が学ぶ HTML タグ (5)導入された HTML タグは、必ずしも XHTML 仕...

nginx で gzip 圧縮を実装してウェブサイトの速度を向上させる方法

目次gzip 圧縮を使用する理由は何ですか? nginxはgzipを実装するgzip処理nginx ...

純粋な CSS 実装 (スクリプトなし) HTML コマンド スタイルのツールチップ テキスト プロンプト効果

実行プロセスを分析します。マウスをノードに移動して、ノードにツールチップ実装を開くための識別子 (...

Linuxはlsof/extundeleteツールを使用して、誤って削除されたファイルやディレクトリを復元します。

序文Linux には Windows のような目立つごみ箱がないため、簡単に復元することはできません...

MySQL 集計関数のネストされた使用操作

目的: MySQL 集計関数のネストされた使用集計関数は直接ネストできません。例: max(coun...

MySQL 8.0.23のルートパスワードをリセットするための最適なソリューション

この方法は2021年2月7日に編集されました。私が使用しているバージョンは8.0.23です。事件の原...

CentOS7 に Redis をインストールして設定する方法

導入Redis を詳しく説明する必要はありません。インストールと設定を始めましょう。インストールソー...

Spring Boot 階層化パッケージング Docker イメージの実践と分析 (推奨)

目次1. Springbootプロジェクトを準備する2. 関連する設定を実行する3.パッケージ4.D...