MYSQL メタデータ ロック (MDL ロック) の理論とロック タイプ テスト

MYSQL メタデータ ロック (MDL ロック) の理論とロック タイプ テスト

MYSQL メタデータ ロック (MDL ロック) 学習理論とロック タイプ テスト

序文:

ソースコードバージョン: 5.7.14
MDLとDMLの用語の違いに注意してください

1. 予備的理解

MYSQL の MDL ロックは常に頭痛の種でした。ロックについて話すとき、通常は INNODB の下位レベルのギャップ ロック、次のキー ロック、行ロックなどについて話す傾向があります。
MDL LOCK は理解しやすく観察しやすいのですが、観察が非常に難しいため、あまり知られていません。問題が発生した場合にのみ、show processlist をチェックして、いわゆるテーブル メタデータ ロックの待機状態をかろうじて確認できます。実際、MDL LOCK は MYSQL 上位層の非常に複雑なサブシステムであり、独自のデッドロック検出メカニズムを備えています。
(無向グラフ?) そして、テーブルがロックされているかどうかとよく言われるのは、実はこれのことを指しています。これは重大で深刻な問題であることがわかります。著者も自分のニーズに応じていくつか(氷山の一角)を学んできました。
すべてのコードを読む能力はありませんが、簡単に勉強できるように、ステートメントのMDL LOCKロックプロセスを印刷するためのTICKET印刷機能を追加しました。以下では、いくつかの基本から始めて、何が変更されたかを説明します。最後に、各MDL TYPEをテストして分析します。基本的な概念と印刷機能の追加に興味がない場合は、ロックテストの第5部を直接参照できますが、基本を理解していない場合は少し難しいように思えるかもしれません。
最近、MDL LOCK でデッドロックに遭遇しました。次の記事で事例を紹介します。ここでは理論だけを見ていきます。

----レベル:MYSQL SERVERレベルでは、実際には、MDL LOCKはopen_table関数で早くも取得されます。これは、最も早く取得されるLOCK構造であると言えます。
---- 最も早い取得段階: THD::enter_stage: 'Opening tables'

呼び出しスタックフレーム:

#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的死鎖拋錯和INNODB死鎖一模一樣不同的只是SHOW ENGINE 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 LOCKに対応します。たとえば、 flush table with read lock namespace space:GLOBAL type:S
オブジェクトロック:その名の通り、 TABLE
などのオブジェクトレベルのMDL LOCKTABLE
ソースコード内のコメントは次のとおりです。

 /**
    さまざまなタイプのロックの処理方法を定義するヘルパー構造体
    特定の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です。

7. MDL_keyクラス

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

  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のロック、アップグレード、ダウングレードのプロセスを理解することです。ソースコードが大きすぎるため、すべてを網羅することは不可能です。5.7では、次のメソッドが追加され、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 LOCK を取得したかを確認することは依然として困難です。そこで、次のように関数プロトタイプを mdl.cc に追加しました

  • /*p_ticket in パラメータ*/
  • int my_print_ticket(const MDL_ticket* p_ticket)

また、 mdl_ticketクラスでは、この関数プロトタイプがフレンド関数として追加されています。そうしないと、プライベートメンバーを取得できず、指定されたパブリックメソッドがより複雑になります。
friend 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 processlistThread 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 操作によってトリガーされるなど、多くの操作で発生します。
DELTE/UPDATE/INSERT/FOR UPDATE などの DML 操作は、GLOBAL に IX ロックを追加し、次にオブジェクトに追加します。DDL ステートメントは、少なくとも GLOBAL に IX ロックを追加し、オブジェクトが属する SCHEMA に IX ロックを追加し、次にオブジェクトに追加します。

以下はDELETEによってトリガーされたGLOABLIX 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)

這把鎖一般用在flush tables with read lock中

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 と互換性がありませんflush tables with read lock; 就會堵塞所有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

這里還是要提及一下平時我們偶爾會出現select也堵住的情況(比如DDL的某個階段需要對象MDL X鎖)。我們不得不抱怨
MYSQL居然會堵塞select其實這里也就是object mdl lock X 和SR 不兼容的問題(參考前面的兼容矩陣)。

5. MDL_SHARED_WRITE(SW)

這把鎖一般用于DELTE/UPDATE/INSERT/FOR UPDATE等操作對table的加鎖(當前讀), 。ただし、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)

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

Used by DML statements modifying
tables and using the LOW_PRIORITY clause

互換性:

       リクエスト | ロックのリクエストを許可しました |
        タイプ | 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どころかINNODBエンジン層に入ることもできません。
DDLでは、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印刷)MDL期間は:MDL_TRANSACTIONです
2017-08-03T19:46:54.856214Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです
2017-08-03T19:47:00.260166Z 3 [注](upgrade_shared_lock)このMDLロックがアップグレードされます
2017-08-03T19:47:00.304057Z 3 [note](upgrade_shared_lock)このMDLロックアップグレード
2017-08-03T19:47:00.304090Z 3 [注](> MDL印刷)スレッドIDは3です。
2017-08-03T19:47:00.304105Z 3 [注]( - > MDL印刷)DB_NAME IS:TEST
2017-08-03T19:47:00.304119Z 3 [注]( - > mdl print)obj_name is:testsort12
2017-08-03T19:47:00.304132Z 3 [注](---> MDL印刷)名前空間はテーブルです
2017-08-03T19:47:00.304181Z 3 [NOTE](-----> MDL Print)MDLタイプIS:MDL_EXCLISIVE(X)
2017-08-03T19:47:00.304196Z 3 [注](------> MDL印刷)MDL期間は:MDL_TRANSACTIONです
2017-08-03T19:47:00.304211Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです
2017-08-03T19:47:01.032329Z 3 [注](ackire_lock)

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

2017-08-03T19:46:54.781487 got 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が実際には、實際在MDL SU模式下所以不會堵塞DML/SELECT操作。
這里再給大家提個醒所謂的ONLINE DDL只是在COPY階段不堵塞DML/SELECT操作,還是盡量在數據庫壓力小的時候,
比如如果有DML沒有提交或者SELECT沒有做完這個時候SW SR必然堵塞X,而X能夠堵塞一切且為高優先級。這樣導致的現象就是由于DML未提交堵塞DDL操作而DDL操作堵塞一切操作,基本對于這個TABLE的表全部堵塞。

アルゴリズム=コピーの場合、コードの残りの部分は同様です但是在COPY階段用的是SNW鎖,接下來我就先來看看SNW鎖

8。MDL_SHARED_NO_WRITE(SNW)

SUはSNWにアップグレードでき、SNWはXにアップグレードできます。これは、アルゴリズム=コピーで使用するために前述のように、データの一貫性を保護するためです。

互換性:

       リクエスト|                   
        タイプ|。
      ----------+---------------------------------------------+
      snw |  -   -  +  -  |


SRは、もちろんDML(SW)をブロックすることはできません
mysql> Table testsort12 column ik int not null、algorithm = copy;

2017-08-03T20:07:58.413215Z 3 [note](upgrade_shared_lock)このMDLロックアップグレード
2017-08-03T20:07:58.413241Z 3 [注](> MDL印刷)スレッドIDは3です。
2017-08-03T20:07:58.413257Z 3 [注]( - > MDL印刷)DB_NAME IS:TEST
2017-08-03T20:07:58.413273Z 3 [注]( - > mdl print)obj_name is:testsort12
2017-08-03T20:07:58.413292Z 3 [注](---> MDL印刷)名前空間はテーブルです
2017-08-03T20:07:58.413308Z 3 [注](-----> MDL印刷)MDLタイプIS:MDL_SHARED_NO_WRITE(SNW)
2017-08-03T20:07:58.413325Z 3 [注](------> MDL印刷)MDL期間は:MDL_TRANSACTIONです
2017-08-03T20:07:58.413341Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです
2017-08-03T20:08:25.392006Z 3 [note](upgrade_shared_lock)このMDLロックアップグレード
2017-08-03T20:08:25.392024Z 3 [note](> mdl print)スレッドIDは3です。
2017-08-03T20:08:25.392086Z 3 [注]( - > MDL印刷)DB_NAME IS:TEST
2017-08-03T20:08:25.392159Z 3 [NOTE]( - > mdl print)obj_name is:testsort12
2017-08-03T20:08:25.392199Z 3 [注](---> MDL印刷)名前空間はテーブルです
2017-08-03T20:08:25.392214Z 3 [Note](-----> MDL Print)MDLタイプIS:MDL_EXCLISIVE(X)
2017-08-03T20:08:25.392228Z 3 [NOTE](------> MDL Print)MDL期間は:MDL_TRANSACTIONです
2017-08-03T20:08:25.392242Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです

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 語句

互換性は次のとおりです

      リクエスト|
        タイプ|。
      ----------+---------------------------------------------+
      sro | + + +  -  + +  -  |


DML(SW)をブロックしても問題ありませんが、選択(SR)はまだ可能です。

mysql> lock table testsort12 read;
クエリは正常、影響を受けた行は 0 行 (0.01 秒)
2017-08-03T21:08:27.267947Z 3 [注](ackire_lock)このMDLロックはOKを取得します!
2017-08-03T21:08:27.267979Z 3 [注](> MDL印刷)スレッドIDは3です。
2017-08-03T21:08:27.268009Z 3 [注]( - > MDL印刷)DB_NAME IS:TEST
2017-08-03T21:08:27.268040Z 3 [注]( - > mdl print)obj_name is:testsort12
2017-08-03T21:08:27.268070Z 3 [注](---> MDL印刷)名前空間はテーブルです
2017-08-03T21:08:27.268113Z 3 [注](-----> MDL印刷)MDLタイプIS:MDL_SHARED_READ_ONLY(SRO)
2017-08-03T21:08:27.268145Z 3 [注](------> MDL印刷)MDL期間は:MDL_TRANSACTIONです
2017-08-03T21:08:27.268175Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです

10。MDL_SHARED_NO_READ_WRITE(SNRW)

用于LOCK TABLES WRITE語句

互換性:

       リクエスト|
        タイプ|。
      ----------+---------------------------------------------+
      snrw |  -  ----- |


DML(SW)とSelect(SR)がブロックされており、SHのみがOKであり、DESC(SH)がOKであることがわかります。

mysql> lock table testsort12 write;
クエリは正常、影響を受けた行は 0 行 (0.00 秒)
2017-08-03T21:13:07.113347Z 3 [Note](quickire_lock)このMDLロックはOKを取得します!
2017-08-03T21:13:07.113407Z 3 [注](> MDL印刷)スレッドIDは3です。
2017-08-03T21:13:07.113435Z 3 [注](---> MDLプリント)名前空間はグローバルです
2017-08-03T21:13:07.113458Z 3 [注](----> MDLプリント)高速パスIS:(Y)
2017-08-03T21:13:07.113482Z 3 [注](-----> MDL印刷)MDLタイプIS:MDL_INTENTENT_EXCLISIVE(IX)
2017-08-03T21:13:07.113505Z 3 [注](------> MDL印刷)MDL期間は:MDL_STATEMENT
2017-08-03T21:13:07.113604Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです
2017-08-03T21:13:07.113637Z 3 [Note](ackire_lock)このMDLロックはOKを取得します!
2017-08-03T21:13:07.113660Z 3 [note](> mdl print)スレッドIDは3です。
2017-08-03T21:13:07.113681Z 3 [注]( - > MDL印刷)DB_NAME IS:TEST
2017-08-03T21:13:07.113703Z 3 [注]( - > mdl print)obj_name is:
2017-08-03T21:13:07.113725Z 3 [注](---> mdl print)名前空間IS:Schema
2017-08-03T21:13:07.113746Z 3 [Note](----> MDL Print)Fast Path is:(Y)
2017-08-03T21:13:07.113768Z 3 [注](-----> MDL印刷)MDLタイプIS:MDL_INTENTENT_EXCLISIVE(IX)
2017-08-03T21:13:07.113791Z 3 [NOTE](------> MDL Print)MDL期間は:MDL_TRANSACTIONです
2017-08-03T21:13:07.113813Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです
2017-08-03T21:13:07.113842Z 3 [注](ackire_lock)このMDLロックはOKを取得します!
2017-08-03T21:13:07.113865Z 3 [注](> MDL印刷)スレッドIDは3です。
2017-08-03T21:13:07.113887Z 3 [注]( - > MDL印刷)DB_NAME IS:TEST
2017-08-03T21:13:07.113922Z 3 [注]( - > mdl print)obj_name is:testsort12
2017-08-03T21:13:07.113945Z 3 [注](---> MDL印刷)名前空間はテーブルです
2017-08-03T21:13:07.113975Z 3 [NOTE](-----> MDL Print)MDLタイプIS:MDL_SHARED_NO_READ_WRITE(SNRW)
2017-08-03T21:13:07.113998Z 3 [NOTE](------> MDL Print)MDL期間は:MDL_TRANSACTIONです
2017-08-03T21:13:07.114021Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです

除此之外lock table 還需要GLOBAL和SCHEMA上的IX鎖,換句話說flush tables with read lock; 會堵塞lock table testsort12 write;但是lock table testsort12 read 卻不會堵塞。

11。MDL_EXCLISIVE(X)

さまざまなDDL操作に使用され、作成/ドロップ/名前のテーブル操作として注釈が付けられました。実際、基本的にすべてのDDLには、上記で分析されたように、このロックが含まれます。
列操作を追加しますが、通常、期間は短いです。

互換性:

       リクエスト|
        タイプ|。
      ----------+---------------------------------------------+
      x |  -  ----- |


上記のすべての偶発的な閉塞はありません。また、今すぐ追加列操作など、すべてによってブロックされています

2017-08-03T19:46:54.804240Z 3 [注](> MDL印刷)スレッドIDは3です。
2017-08-03T19:46:54.804254Z 3 [注]( - > MDL印刷)DB_NAME IS:TEST
2017-08-03T19:46:54.804267Z 3 [注]( - > mdl print)obj_name is:testsort12
2017-08-03T19:46:54.804280Z 3 [注](---> MDL印刷)名前空間はテーブルです
2017-08-03T19:46:54.804293Z 3 [注](-----> MDL印刷)MDLタイプIS:MDL_EXCLISIVE(X)
2017-08-03T19:46:54.804306Z 3 [注](------> MDL印刷)MDL期間は:MDL_TRANSACTIONです
2017-08-03T19:46:54.804319Z 3 [注](-------> MDL印刷)MDLステータスは次のとおりです

6。ソースコードコメントセクション

enum enum_mdl_type {
  /*
    スコープロックにのみ使用される排他的なメタデータ。
    このタイプのロックの所有者は、アップグレード可能な排他的ロックを取得できます
    個々のオブジェクト。
    他のIXロックと互換性がありますが、スコープされたSと互換性があります
    Xロック。
  */
  mdl_intentent_exclusive = 0、
  /*
    共有メタデータロック。
    オブジェクトメタデータのみに興味がある場合にのみ使用する
    そして、オブジェクトデータにアクセスするつもりはありません(たとえば、保存されている場合
    ルーチンまたは準備中に準備されたステートメント)。
    また、ロック以来、オープンハンドラーのためにこのタイプのロックを誤用します
    この声明で取得された声明は、取得したロックと互換性がなければなりません
    テーブルをロックすることで...ステートメントを書きます。つまり、snrw(
    ハンドラーでsロックを取得...営業時間とsrにアップグレードする
    ハンドラーのロック...それは必要との問題を解決しないので読む
    テーブルレベルのロックを待っている間に待っているDMLステートメントを中止するには
    同じ接続でハンドラーを開きます)。
    SNRWロックがアップグレードされているときに発生する可能性のあるデッドロックを避けるために
    Xが所有するアクティブSロックがあるテーブル用ロック
    スレッドで所有されているテーブルレベルのロックを順番に待つスレッド
    アップグレードを実行すると、thr_abort_locks_for_thread()を使用する必要があります
    そのような状況にある施設。
    この問題は、保存されているルーチンのロックでは発生しません。
    SNRWロックを使用してください。
    テーブルレベルのロックがこれで取得されないようにコールを準備中
    場合。
  */
  mdl_shared、
  /*
    優先度の高いメタデータロック。
    オブジェクトデータにアクセスする意図がない場合に使用されます(つまり
    テーブル内のデータ)。
    「優先度の高い」とは、他の共有ロックとは異なり、付与されることを意味します
    排他的なロックの保留中のリクエストを無視します
    データではなくメタデータのみにアクセスする必要がある場合、例えば
    Information_schemaテーブルの記入。
    SHロックはSNRWロックと互換性があるため、接続
    保持SHロックロックは、いかなる種類のテーブルレベルを取得しようとしないでください
    または、これがさらにデッドロックにつながる可能性があるため、行レベルのロック
    SHロックを取得すると、接続は他のものを待ってはいけません
    リソースは、xロックと潜在能力の飢vを引き起こす可能性があるため
    SNWまたはSNRWからXロックのアップグレード中のデッドロック(例:
    接続のアップグレードは、待機中のリソースを保持します)。
  */
  mdl_shared_high_prio、
  /*
    データを読み取る意図がある場合の共有メタデータロック
    テーブルから。
    この種のロックを保持する接続は、テーブルメタデータを読み取って読むことができます
    テーブルデータ(適切なテーブルと行レベルのロックを取得した後)。
    これは、tl_read、tl_read_no_insertのみを取得できることを意味します。
    SR MDLロックを保持している場合、同様のテーブルレベルのロックがテーブルにロックされています。
    選択、サブ征服、ロックテーブルのテーブルに使用するには...読み取ります
    ステートメント。
  */
  mdl_shared_read、
  /*
    変更する意図がある場合の場合の共有メタデータロック
    テーブル内のデータ。
    SWロックを保持する接続は、テーブルメタデータを読み取り、変更または読み取ります
    テーブルデータ(適切なテーブルと行レベルのロックを取得した後)。
    挿入、更新、削除によって変更されるテーブルに使用される
    ステートメントは、テーブルをロックしていません...書き込みまたはddl)
    選択...更新用。
  */
  mdl_shared_write、
  /*
    優先度が低いmdl_shared_writeロックのバージョン
    MDL_SHARED_READ_ONLYロック
    テーブルおよびLOW_PRIORITY句の使用。
  */
  mdl_shared_write_low_prio、
  /*
    同時の更新を可能にするアップグレード可能な共有メタデータロック
    テーブルデータの読み取り。
    この種のロックを保持する接続は、テーブルメタデータを読み取って読むことができます
    このロックが互換性があるため、テーブルデータを変更する必要はありません。
    SROロック。
    SUL、XロックがXにアップグレードされると、SNW、SNRW、Xにアップグレードできます
    または、SNRWロックデータの変更は自由に発生する可能性があります。
    Alter Tableの最初のフェーズに使用されます。
  */
  mdl_shared_upgradable、
  /*
    テーブルからデータを読む必要がある場合のケースの共有メタデータロック
    すべての同時変更をブロックします(データとメタデータの両方に対して)。
    ロックテーブルの読み取りステートメントで使用されます。
  */
  mdl_shared_read_only、
  /*
    更新のすべての試みをブロックするアップグレード可能な共有メタデータロック
    テーブルデータ、読み取りを許可します。
    この種のロックを保持する接続は、テーブルメタデータを読み取って読むことができます
    テーブルデータ。
    Xメタデータロックにアップグレードできます。
    このタイプのロックはSNRWまたはSWと互換性がないため、
    ロックタイプ、読み取りのための適切なエンジンレベルのロックを取得します
    (tl_read* myisamの場合、innodbの共有行ロック)
    コンテンツフリー。
    Alter Tableの最初のフェーズに使用するには、間にデータをコピーするときに
    テーブル、同時にテーブルから選択を許可するが、更新は選択しない。
  */
  mdl_shared_no_write、
  /*
    他の接続を可能にするアップグレード可能な共有メタデータロック
    テーブルメタデータにアクセスしますが、データではありません。
    テーブルデータの読み取りまたは更新のすべての試みをブロックし、許可します
    Information_schemaおよびshow queries。
    この種のロックを保持する接続は、テーブルメタデータを変更して読み取り、
    テーブルデータを読んでください。
    Xメタデータロックにアップグレードできます。
    テーブルをロックするために使用するには、ステートメントを書き込みます。
    SおよびSHを除く他のロックタイプと互換性がありません。
  */
  mdl_shared_no_read_write、
  /*
    排他的なメタデータロック。
    このロックを保持する接続は、テーブルのメタデータとデータの両方を変更できます。
    このロックが保持されている間、他のタイプのメタデータロックを許可することはできません。
    テーブルステートメントの作成/ドロップ/名前の変更および実行に使用されます
    他のDDLステートメントの特定のフェーズ。
  */
  mdl_exclusive、
  / *これは最後です!!!
  mdl_type_end};


/**メタデータロックの期間。

enum enum_mdl_duration {
  /**
    ステートメントの期間があるロックは、最後に自動的にリリースされます
    ステートメントまたはトランザクションの。
  */
  mdl_statement = 0、
  /**
    トランザクション期間があるロックは、最後に自動的にリリースされます
    トランザクションの。
  */
  mdl_transaction、
  /**
    明示的な持続時間のロックは、声明とトランザクションの終わりに耐えます。
    それらは、mdl_context :: release_lock()を呼び出すことにより、明示的にリリースする必要があります。
  */
  mdl_explicit、
  / *これは最後です!
  mdl_duration_end};

/**
    オブジェクト名空間。
    sic:この列に新しいメンバーを追加するときは、
    mdlでm_namespace_to_wait_state_name配列を更新します。

    さまざまな種類のオブジェクトが異なる名前空間に存在します
     -Globalは、グローバル読み取りロックに使用されます。
      - テーブルスペースはテーブルスペース用です。
      - スキーマはスキーマ用です(別名データベース)。
      - テーブルはテーブルとビュー用です。
      - 関数は保存された関数用です。
      - 手順はストアドプロシージャ用です。
      - トリガーはトリガー用です。
      - イベントはイベントスケジューライベント用です。
      - コミットは、グローバル読み取りロックがコミットをブロックできるようにするためです。
     -user_level_lockは、ユーザーレベルのロック用です。
     -Locking_Serviceは、名前プラグインRWロックサービス用です
    トリガーにメタデータロックがありませんが、
    それ以来、彼らのために別の名前空間を持つ必要があります
    MDL_KEYは、MDLサブシステムの外でも使用されます。
    また、ユーザーレベルのロックを待つリクエストが特別になることに注意してください
    治療 - クライアントへの接続が失われた場合、待機が中止されます。
  */
  enum enum_mdl_namespace {global = 0、
                            テーブルスペース、
                            スキーマ、
                            テーブル、
                            関数、
                            手順、
                            トリガー、
                            イベント、
                            専念、
                            user_level_lock、
                            locking_service、
                            バックアップ、
                            ビンログ、
                            / *これは最後です!
                            namespace_end};

上記は、MySQL Metadata Lock(MDL Lock)理論とロックタイプテストの詳細な内容です。MySQLメタデータロック(MDLロック)の詳細については、123WordPress.comの他の関連記事に注意してください。

以下もご興味があるかもしれません:
  • mysqlでテーブルメタデータロックを待つ方法
  • mysqlテーブル構造の変更について知っておく必要があるメタデータロックの詳細な説明
  • MySQLメタデータロック(MDLロック)MDLロックの問題の分析
  • MySQLスレーブは、外部キーチェックと自己障害のロックの列を遅らせます
  • MySQL Next-Key Lock Lock Rangeに関する簡単な議論
  • MySQL ロック制御同時実行方法
  • PHP+MySQL の高同時ロックトランザクション処理問題の解決方法

<<:  フレックスレイアウトのスペース間の最後の行の左揃えの問題を解決する方法

>>:  JavaScript 高度なカスタム例外

推薦する

フレックスとポジションの互換性の詳細な説明マイニングノート

今日は、すべてのブラウザ (主に IE 9 以上と Chrome) と互換性のある自分のホームページ...

getdata テーブル テーブル データ 結合 mysql メソッド

パブリック関数 json_product_list($where, $order){ グローバル ...

IPとポートが接続可能かどうかを検出する方法

Windows コマンドテルネット形式: telnet IP ポート場合: テルネット 191.1....

CocosCreatorでリストを作成する方法

CocosCreator バージョン: 2.3.4 Cocos には List コンポーネントがない...

DockerはPruneコマンドを使用してnoneイメージをクリーンアップします

目次無イメージの創造と混乱Noneオブジェクトをクリーンアップする方法トリムミラーコンテナで使用され...

vue-router を遅延ロードする 3 つの方法のまとめ

遅延読み込みを使用しない 'vue' から Vue をインポートします。 '...

CSS と JavaScript を使用して管理ダッシュボードのレイアウトを構築するためのサンプル コード

あなたが作成するものこの新しいチュートリアルでは、CSS と JavaScript を使用して、レス...

HTMLとは何ですか?

HTML 開発の歴史: HTML は英語で Hypertext Marked Language の...

Windows での MySQL のダウンロード、インストール、設定、使用に関するチュートリアル

MySQLの概要MySQL はリレーショナル データベース管理システムです。データベースは構造化され...

Mysql通信プロトコルの詳細な説明

1.Mysql接続方法MySQL 通信プロトコルを理解するには、まず MySQL サーバーへの接続に...

Docker の NFS-Ganesha イメージを使用して NFS サーバーを構築する詳細なプロセス

目次1. NFS-Ganeshaの紹介2. NFS-Ganeshaの設定3. NFS-Ganesha...

CSS 画像アニメーション効果のサンプルコード(フォトフレーム)

この記事では、CSS 画像アニメーション効果(フォトフレーム)のサンプルコードを紹介し、皆さんと共有...

HTML タグ dl dt dd 使用方法

基本構造:コードをコピーコードは次のとおりです。 <ダウンロード> <dt>...

XHTMLタグには終了タグがある

<br />オリジナルリンク: http://www.dudo.org/article....

Vue の better-scroll コンポーネントを使用して水平スクロール機能を実現する

について最近、Vue を学習する過程で、基本的な知識の練習と強化を目的として、Qunar.com の...