日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 數據庫 > MySQL > 正文

MYSQL METADATA LOCK(MDL LOCK)MDL鎖問題分析

2024-07-24 13:15:13
字體:
來源:轉載
供稿:網友

一、前言

MYSQL中MDL鎖一直是一個比較讓人比較頭疼的問題,我們談起鎖一般更加傾向于INNODB下層的gap lock、next key lock、row lock等,因為它很好理解,也很好觀察,而對于MDL LOCK卻了解得很少,因為它實在不好觀察,只有出現問題查看show processlist勉強可以看到

簡單的所謂的Waiting for table metadata lock之類的狀態,其實MDL LOCK是MYSQL上層一個非常復雜的子系統,有自己的死鎖檢測機制

(無向圖?)而大家一般口中的是不是鎖表了其實就是指的它,可見的它的關鍵性和嚴重性,筆者也是根據自己的需求學習了一些(冰山一角),而沒有能力閱讀全部的代碼,但是筆者通過增加一個TICKET的打印函數讓語句的MDL LOCK加鎖流程全部打印出來方便學習研究,下面從一些基礎說起然后告訴大家修改了哪些東西,最后對每種MDL TYPE進行測試和分析,如果大家對基本概念和增加打印函數不感興趣可直接參考第五部分加鎖測試,但是如果不了解基礎知識可能看起來有點困難。

剛好最近遇到一次MDL LOCK出現死鎖的情況會在下篇文章中給出案例,這里只看理論

----處于層次:MYSQL SERVER層次,實際上早在open_table函數中MDL LOCK就開始獲取了,可以說他是最早獲取的LOCK結構

----最早獲取階段: THD::enter_stage: 'Opening tables'

調用棧幀

#0 open_table_get_mdl_lock (thd=0x7fffd0000df0, ot_ctx=0x7fffec06fb00,   table_list=0x7fffd00067d8, flags=0, mdl_ticket=0x7fffec06f950)  at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:2789#1 0x0000000001516e17 in open_table (thd=0x7fffd0000df0,   table_list=0x7fffd00067d8, ot_ctx=0x7fffec06fb00)  at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:3237

----死鎖檢測出錯碼:

{ "ER_LOCK_DEADLOCK", 1213, "Deadlock found when trying to get lock; try restarting transaction" },ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

MDL LOCK的死鎖拋錯和INNODB死鎖一模一樣不同的只是SHOW ENGINE INNODB 沒有死鎖信息。

----涉及代碼:mdl.h mdl.cc

二、基礎重要的數據結構(類)和概念

1、MDL TYPE

MDL_INTENTION_EXCLUSIVE(IX)

MDL_SHARED(S)

MDL_SHARED_HIGH_PRIO(SH)

MDL_SHARED_READ(SR)

MDL_SHARED_WRITE(SW)

MDL_SHARED_WRITE_LOW_PRIO(SWL)

MDL_SHARED_UPGRADABLE(SU)

MDL_SHARED_READ_ONLY(SRO)

MDL_SHARED_NO_WRITE(SNW)

MDL_SHARED_NO_READ_WRITE(SNRW)

MDL_EXCLUSIVE(X)

后面會對每種TYPE進行詳細的測試,最后也會給出源碼中解釋

2、MDL NAMESPACE

在MDL中MDL_KEY按照NAMESPACE+DB+OBJECT_NAME的方式進行表示,所謂的namespace也不叫重要

下面是NAMESPACE的分類

- GLOBAL is used for the global read lock.

- TABLESPACE is for tablespaces.

- SCHEMA is for schemas (aka databases).

- TABLE is for tables and views.

- FUNCTION is for stored functions.

- PROCEDURE is for stored procedures.

- TRIGGER is for triggers.

- EVENT is for event scheduler events.

- COMMIT is for enabling the global read lock to block commits.

- USER_LEVEL_LOCK is for user-level locks.

- LOCKING_SERVICE is for the name plugin RW-lock service

3、實現分類

scope lock:一般對應全局MDL LOCK 如flush table with read lock 為namespace space:GLOBAL type:S

object lock:如其名字,對象級別的MDL LOCK,比如TABLE

下面是源碼中的注釋:

 /**  Helper struct which defines how different types of locks are handled  for a specific MDL_lock. In practice we use only two strategies: "scoped"  lock strategy for locks in GLOBAL, COMMIT, TABLESPACE and SCHEMA namespaces  and "object" lock strategy for all other namespaces. */

4、MDL兼容矩陣

scope lock:     | Type of active  | Request |  scoped lock  |  type  | IS(*) IX  S X | ---------+------------------+ IS    | +   +  + + | IX    | +   +  - - | S    | +   -  + - | X    | +   -  - - |object lock:    Request | Granted requests for lock      |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   S     | +  +  +  +  +  +  +  +  +  - |   SH    | +  +  +  +  +  +  +  +  +  - |   SR    | +  +  +  +  +  +  +  +  -  - |   SW    | +  +  +  +  +  +  -  -  -  - |   SWLP   | +  +  +  +  +  +  -  -  -  - |   SU    | +  +  +  +  +  -  +  -  -  - |   SRO    | +  +  +  -  -  +  +  +  -  - |   SNW    | +  +  +  -  -  -  +  -  -  - |   SNRW   | +  +  -  -  -  -  -  -  -  - |   X     | -  -  -  -  -  -  -  -  -  - |

5、MDL duration及MDL持續到什么時候

這個也不多用過多解釋,看源碼注釋即可

MDL_STATEMENT:Locks with statement duration are automatically released at the end       of statement or transaction.MDL_TRANSACTION: Locks with transaction duration are automatically released at the end        of transactionMDL_EXPLICIT:Locks with explicit duration survive the end of statement and transaction.       They have to be released explicitly by calling MDL_context::release_lock().

6、MDL LOCK FAST PATH(unobtrusive) OR SLOW PATH(obtrusive)

使用兩種不同的方式目的在于優化MDL lock的實現,下面是源碼的注釋

A) "unobtrusive" lock types      1) Each type from this set should be compatible with all other        types from the set (including itself).      2) These types should be common for DML operations     Our goal is to optimize acquisition and release of locks of this     type by avoiding complex checks and manipulations on m_waiting/     m_granted bitmaps/lists. We replace them with a check of and     increment/decrement of integer counters.     We call the latter type of acquisition/release "fast path".     Use of "fast path" reduces the size of critical section associated     with MDL_lock::m_rwlock lock in the common case and thus increases     scalability.     The amount by which acquisition/release of specific type     "unobtrusive" lock increases/decreases packed counter in     MDL_lock::m_fast_path_state is returned by this function.B) "obtrusive" lock types      1) Granted or pending lock of those type is incompatible with        some other types of locks or with itself.      2) Not common for DML operations     These locks have to be always acquired involving manipulations on     m_waiting/m_granted bitmaps/lists, i.e. we have to use "slow path"     for them. Moreover in the presence of active/pending locks from     "obtrusive" set we have to acquire using "slow path" even locks of     "unobtrusive" type.

7、MDL_request類

也就是通過語句解析后需要獲得的MDL LOCK的需求,然后通過這個類對象在MDL子系統
中進行MDL LOCK申請,大概包含如下一些屬性

/** Type of metadata lock. */ enum enum_mdl_type type; //需求的類型 /** Duration for requested lock. */ enum enum_mdl_duration duration; //持續時間 /**  Pointers for participating in the list of lock requests for this context. */ MDL_request *next_in_list; //雙向鏈表實現 MDL_request **prev_in_list; /**  Pointer to the lock ticket object for this lock request.  Valid only if this lock request is satisfied. */ MDL_ticket *ticket; //注意這里如果申請成功(沒有等待),會指向一個實際的TICKET,否則為NULL /** A lock is requested based on a fully qualified name and type. */ MDL_key key;//注意這里是一個MDL_KEY類型,主要的就是前面說的NAMESPACE+DB+OBJECT_NAME

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_ticket

如同門票一樣,如果獲取了MDL LOCK必然給MDL_request返回一張門票,如果等待則不會源碼MDL_context::acquire_lock

可以觀察到。當然這也是我主要觀察的一個類

/**  Pointers for participating in the list of lock requests for this context.  Context private.正如解釋這里是context中鏈表鏈表的形成,是線程私有的 */ MDL_ticket *next_in_context; MDL_ticket **prev_in_context; /**  Pointers for participating in the list of satisfied/pending requests  for the lock. Externally accessible.正如解釋這里是MDL_LOCK中鏈表鏈表的形成,是全局的 */ MDL_ticket *next_in_lock; MDL_ticket **prev_in_lock;/**  Context of the owner of the metadata lock ticket. Externally accessible.  很明顯這里指向了這個ticket的擁有者也就是MDL_context,它是線程的屬性 */ MDL_context *m_ctx;  /**  Pointer to the lock object for this lock ticket. Externally accessible.  很明顯這里是一個指向MDL_LOCK的一個指針 */ MDL_lock *m_lock; /**  Indicates that ticket corresponds to lock acquired using "fast path"  algorithm. Particularly this means that it was not included into  MDL_lock::m_granted bitmap/list and instead is accounted for by  MDL_lock::m_fast_path_locks_granted_counter  這里就代表了是否是FAST PATH從注釋來看fast path方式不會在MDL LOCK中  占用granted位圖和鏈表取而代之代之的是一個統計器m_fast_path_locks_granted_counter  這樣一來開銷肯定更小 */ bool m_is_fast_path; /**  Indicates that ticket corresponds to lock request which required  storage engine notification during its acquisition and requires  storage engine notification after its release. */ bool m_hton_notified;

9、MDL_lock

每一個MDL_key都會對應一個MDL_lock,其中包含了所謂的GRANTED鏈表和WAIT鏈表,考慮它的復雜性,可以直接參考源碼注釋也非常詳細,這里給出我所描述的幾個屬性。

/** The key of the object (data) being protected. */

MDL_key key;

/** List of granted tickets for this lock. */

Ticket_list m_granted;

/** Tickets for contexts waiting to acquire a lock. */

Ticket_list m_waiting;

10、MDL_context

這是整個MYSQL 線程和MDL lock子系統進行交互的一個所謂的上下文結構其中包含了很多方法和屬性,我比較關注的屬性如下:

/**  If our request for a lock is scheduled, or aborted by the deadlock  detector, the result is recorded in this class. */ MDL_wait m_wait;/**  Lists of all MDL tickets acquired by this connection.  這是一個不同MDL lock持續時間的一個鏈表數組。實際就是  MDL_STATEMENT一個鏈表  MDL_TRANSACTION一個鏈表  MDL_EXPLICIT一個鏈表 */Ticket_list m_tickets[MDL_DURATION_END];//這是一個父類指針指向子類對象,虛函數重寫的典型,實際他就指向了一個線程/*class THD :public MDL_context_owner,      public Query_arena,      public Open_tables_state*/MDL_context_owner *m_owner;

11、MDL_wait

這個類主要是當前ticket獲取狀態

enum_wait_status m_wait_status;

包含

EMPTY 初始化

GRANTED 獲取成功

VICTIM 死鎖

TIMEOUT 超時

KILLED KILLED

12、等待標記

PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]={ {0, "Waiting for global read lock", 0}, {0, "Waiting for tablespace metadata lock", 0}, {0, "Waiting for schema metadata lock", 0}, {0, "Waiting for table metadata lock", 0}, {0, "Waiting for stored function metadata lock", 0}, {0, "Waiting for stored procedure metadata lock", 0}, {0, "Waiting for trigger metadata lock", 0}, {0, "Waiting for event metadata lock", 0}, {0, "Waiting for commit lock", 0}, {0, "User lock", 0}, /* Be compatible with old status. */ {0, "Waiting for locking service lock", 0}, {0, "Waiting for backup lock", 0}, {0, "Waiting for binlog lock", 0}};

三、增加MDL LOCK打印函數

研究MDL LOCK鎖最好的方式當然是能夠獲取MDL 加鎖、升級、降級的流程,因為源碼太龐大了,不可能面面俱到
雖然5.7加入了

UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME ='global_instrumentation';

UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME ='wait/lock/metadata/sql/mdl';

select * from performance_schema.metadata_locks

的方式進行MDL LOCK的查看,但是如果要觀察一個語句到底獲取了哪些MDL LOCK還是顯得無力所以筆者在mdl.cc中加入了一個函數原型如下

/*p_ticket in parameter*/

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 lock database name 通過p_ticket->m_lock->key.db_name()獲取

mdl lock object name 通過p_ticket->m_lock->key.name()獲取

mdl lock namespace 通過p_ticket->m_lock->key.mdl_namespace()獲取

mdl lock fast path 通過p_ticket->m_is_fast_path獲取判斷是則輸出否則不輸出

mdl lock type 通過p_ticket->m_type獲取

mdl lock duration 通過p_ticket->m_duration獲取

輸出信息如下:

2017-08-03T07:34:21.720583Z 3 [Note] (>MDL PRINT) Thread id is 3:

2017-08-03T07:34:21.720601Z 3 [Note] (->MDL PRINT) DB_name is:test

2017-08-03T07:34:21.720619Z 3 [Note] (-->MDL PRINT) OBJ_name is:test

2017-08-03T07:34:21.720637Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE

2017-08-03T07:34:21.720655Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)

2017-08-03T07:34:21.720673Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_WRITE(SW)

2017-08-03T07:34:21.720692Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION

實際上和metadata_locks中的信息差不多,這是我這里的Thread id 是show processlist出來的id,但是我可以獲得鎖獲取的歷史信息,我這里同時沒有 LOCK_STATUS: GRANTED,但是可以在MDL_context::acquire_lock 邏輯上可以判斷出來

mysql> select * from performance_schema.metadata_locks/G*************************** 1. row ***************************OBJECT_TYPE: TABLEOBJECT_SCHEMA: testOBJECT_NAME: testOBJECT_INSTANCE_BEGIN: 140734412907760LOCK_TYPE: SHARED_WRITELOCK_DURATION: TRANSACTIONLOCK_STATUS: GRANTEDSOURCE: sql_parse.cc:6314OWNER_THREAD_ID: 39OWNER_EVENT_ID: 241

四、在合適的位置增加打印函數進行觀察

既然我們要研究MDL LOCK的加鎖/升級/降級、那么我們就必要找到他們的函數入口,然后在合適的位置增加打印函數進行觀察,下面標示出打印位置,刪除了大部分的源代碼,需要參考請自行查看源碼

1、加鎖:MDL_context::acquire_lock

boolMDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout){ if (mdl_request->ticket) //獲取成功獲得ticket {  /*   We have managed to acquire lock without waiting.   MDL_lock, MDL_context and MDL_request were updated   accordingly, so we can simply return success.  */  //REQUESET獲取TICKET成功 此處打印  return FALSE; } /*  Our attempt to acquire lock without waiting has failed.  As a result of this attempt we got MDL_ticket with m_lock  member pointing to the corresponding MDL_lock object which  has MDL_lock::m_rwlock write-locked. */ //獲取不成功加入MDL_lock 等待隊列 lock= ticket->m_lock; lock->m_waiting.add_ticket(ticket); will_wait_for(ticket); //死鎖檢測 /* There is a shared or exclusive lock on the object. */ DEBUG_SYNC(get_thd(), "mdl_acquire_lock_wait"); find_deadlock();  //此處打印TICKET進入了等待流程 if (lock->needs_notification(ticket) || lock->needs_connection_check()) {  } done_waiting_for();//等待完成對死鎖檢測等待圖進行調整去掉本等待邊edge(無向圖) //當然到這里也是通過等待后獲得成功了狀態為GRANTED DBUG_ASSERT(wait_status == MDL_wait::GRANTED); m_tickets[mdl_request->duration].push_front(ticket); mdl_request->ticket= ticket; mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED); //此處打印通過等待REQUEST獲得了TICKET return FALSE;}

2、降級:void MDL_ticket::downgrade_lock(enum_mdl_type new_type)

void MDL_ticket::downgrade_lock(enum_mdl_type new_type){ /* Only allow downgrade from EXCLUSIVE and SHARED_NO_WRITE. */ DBUG_ASSERT(m_type == MDL_EXCLUSIVE ||       m_type == MDL_SHARED_NO_WRITE);//此處打印出降級前的TICKET if (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)

boolMDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,                 enum_mdl_type new_type,                 ulong lock_wait_timeout){ MDL_REQUEST_INIT_BY_KEY(&mdl_new_lock_request,             &mdl_ticket->m_lock->key, new_type,             MDL_TRANSACTION);//構造一個request //此處打印出來的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); lock= mdl_ticket->m_lock; //下面進行一系列對MDL_LOCK的維護并且對所謂的合并操作 /* Code below assumes that we were upgrading to "obtrusive" type of lock. */ DBUG_ASSERT(lock->is_obtrusive_lock(new_type)); /* Merge the acquired and the original lock. @todo: move to a method. */ mysql_prlock_wrlock(&lock->m_rwlock); if (is_new_ticket) {  m_tickets[MDL_TRANSACTION].remove(mdl_new_lock_request.ticket);  MDL_ticket::destroy(mdl_new_lock_request.ticket); } //此處打印出來的升級后TICKET類型  DBUG_RETURN(FALSE);}

當然我現在只是在這些地方進行了打印,以后如果需要在其他地方答應加上函數就可以了。

五、各種MDL LOCK TYPE加鎖測試

1、MDL_INTENTION_EXCLUSIVE(IX)

這個鎖會在很多操作的時候都會出現比如做任何一個DML/DDL 操作都會觸發,實際上DELTE/UPDATE/INSERT/FOR UPDATE等DML操作會在GLOBAL 上加IX鎖 然后才會在本對象上加鎖而DDL 語句至少會在GLOBAL 上加IX鎖,對象所屬 SCHEMA上加IX鎖,本對象加鎖下面是 DELETE 觸發的 GLOABL IX MDL LOCK

2017-08-03T18:22:38.092100Z 3 [Note] Test2:open_tables_for_query()2017-08-03T18:22:38.092205Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T18:22:38.092242Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T18:22:38.092276Z 3 [Note] (--->MDL PRINT) Namespace is:GLOBAL 2017-08-03T18:22:38.092310Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T18:22:38.092344Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T18:22:38.092380Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_STATEMENT 2017-08-03T18:22:38.092551Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

下面是 ALETER 語句觸發的GLOABL IX MDL LOCK以及SCHEMA級別的MDL LOCK

2017-08-03T18:46:05.894871Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T18:46:05.894915Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T18:46:05.894948Z 3 [Note] (--->MDL PRINT) Namespace is:GLOBAL 2017-08-03T18:46:05.894980Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T18:46:05.895012Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T18:46:05.895044Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_STATEMENT 2017-08-03T18:46:05.895076Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T18:46:05.895116Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T18:46:05.895147Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T18:46:05.895206Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T18:46:05.895243Z 3 [Note] (-->MDL PRINT) OBJ_name is: 2017-08-03T18:46:05.895276Z 3 [Note] (--->MDL PRINT) Namespace is:SCHEMA 2017-08-03T18:46:05.895325Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T18:46:05.895357Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T18:46:05.895390Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T18:46:05.895421Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

所以這個MDL LOCK 無所不在,而只有是否兼容問題,如果不兼容則堵塞。SCOPED 的IX類型一般都是兼容的除非遇到
S類型

2、MDL_SHARED(S)

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

mysql> flush tables with read lock;Query OK, 0 rows affected (0.01 sec)2017-08-03T18:19:11.603911Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T18:19:11.603947Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T18:19:11.603971Z 3 [Note] (--->MDL PRINT) Namespace is:GLOBAL 2017-08-03T18:19:11.603994Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED(S) 2017-08-03T18:19:11.604045Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_EXPLICIT 2017-08-03T18:19:11.604073Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T18:19:11.604133Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T18:19:11.604156Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T18:19:11.604194Z 3 [Note] (--->MDL PRINT) Namespace is:COMMIT 2017-08-03T18:19:11.604217Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED(S) 2017-08-03T18:19:11.604240Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_EXPLICIT 2017-08-03T18:19:11.604310Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

我們注意到其namspace為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操作

兼容性:

    Request | Granted requests for lock         |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   SH    | +  +  +  +  +  +  +  +  +  - |mysql> desc test.testsort10;2017-08-03T19:06:05.843277Z 4 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T19:06:05.843324Z 4 [Note] (>MDL PRINT) Thread id is 4: 2017-08-03T19:06:05.843359Z 4 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:06:05.843392Z 4 [Note] (-->MDL PRINT) OBJ_name is:testsort10 2017-08-03T19:06:05.843425Z 4 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:06:05.843456Z 4 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T19:06:05.843506Z 4 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_HIGH_PRIO(SH) 2017-08-03T19:06:05.843538Z 4 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:06:05.843570Z 4 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

這中類型的優先級比較高,但是其和X不兼容。也很好理解比如在rename 階段肯定不能進行desc操作。

4、MDL_SHARED_READ(SR)

這把鎖一般用在非當前讀取的select中兼容性:

    Request | Granted requests for lock         |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   SR    | +  +  +  +  +     +   +    +  -  - |mysql> select * from test.testsort10 limit 1;2017-08-03T19:13:52.338764Z 4 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T19:13:52.338813Z 4 [Note] (>MDL PRINT) Thread id is 4: 2017-08-03T19:13:52.338847Z 4 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:13:52.338883Z 4 [Note] (-->MDL PRINT) OBJ_name is:testsort10 2017-08-03T19:13:52.338917Z 4 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:13:52.338950Z 4 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T19:13:52.339025Z 4 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ(SR) 2017-08-03T19:13:52.339062Z 4 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:13:52.339097Z 4 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

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

5、MDL_SHARED_WRITE(SW)

這把鎖一般用于DELTE/UPDATE/INSERT/FOR UPDATE等操作對table的加鎖(當前讀),不包含DDL操作
但是要注意DML操作實際上會有一個GLOBAL的IX的鎖,前面已經提及過了,這把鎖只是對象上的

兼容性:

    Request | Granted requests for lock         |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   SW    | +  +  +  +  +  +  -  -  -  - |mysql> select * from test.testsort10 limit 1 for update;2017-08-03T19:25:41.218428Z 4 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T19:25:41.218461Z 4 [Note] (>MDL PRINT) Thread id is 4: 2017-08-03T19:25:41.218493Z 4 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:25:41.218525Z 4 [Note] (-->MDL PRINT) OBJ_name is:testsort10 2017-08-03T19:25:41.218557Z 4 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:25:41.218588Z 4 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T19:25:41.218620Z 4 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_WRITE(SW) 2017-08-03T19:25:41.218677Z 4 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:25:41.218874Z 4 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

6、MDL_SHARED_WRITE_LOW_PRIO(SWL)

這把鎖很少用到源碼注釋只有

Used by DML statements modifying

tables and using the LOW_PRIORITY clause

會用到

兼容性:

    Request | Granted requests for lock         |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   SWLP   | +  +  +  +  +  +  -  -  -  - |mysql> update LOW_PRIORITY test.testsort10 set id1=1000 where id1= 96282;2017-08-03T19:32:47.433507Z 4 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T19:32:47.433521Z 4 [Note] (>MDL PRINT) Thread id is 4: 2017-08-03T19:32:47.433533Z 4 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:32:47.433547Z 4 [Note] (-->MDL PRINT) OBJ_name is:testsort10 2017-08-03T19:32:47.433560Z 4 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:32:47.433572Z 4 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T19:32:47.433594Z 4 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_WRITE_LOW_PRIO(SWL) 2017-08-03T19:32:47.433607Z 4 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:32:47.433620Z 4 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

7、MDL_SHARED_UPGRADABLE(SU)

這把鎖一般在ALTER TABLE語句中用到,他可以升級為SNW, SNRW,X,同時至少X鎖也可以降級為SU

實際上在INNODB ONLINE DDL中非常依賴于他,DML(SW)和SELECT(SR)都不會堵塞

兼容性:

    Request | Granted requests for lock         |    type  | 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的根基,如果不兼容你都進入不了INNODB引擎層,更談不上什么ONLINE DDL,注意我這里說的ALGORITHM=INPLACE 并且不設置LOCK

(For DDL operations with LOCK=DEFAULT, or with the LOCK clause omitted, MySQL uses the lowest level
of locking that is available for that kind of operation, allowing concurrent queries, DML, or both wherever
possible. This is the setting to use when making pre-planned, pre-tested changes that you know will not
cause any availability problems based on the workload for that table
When an operation on the primary key uses ALGORITHM=INPLACE, even though the data is still copied, it
is more efficient than using ALGORITHM=COPY because:
? No undo logging or associated redo logging is required for ALGORITHM=INPLACE. These operations add
overhead to DDL statements that use ALGORITHM=COPY.
? The secondary index entries are pre-sorted, and so can be loaded in order.
? The change buffer is not used, because there are no random-access inserts into the secondary indexes.
)

如下面的語句

mysql> alter table testsort12 add column it int not null;
Query OK, 0 rows affected (6.27 sec)
Records: 0 Duplicates: 0 Warnings: 0

我簡單的分析一下:

2017-08-03T19:46:54.781453Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T19:46:54.781487Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T19:46:54.781948Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:46:54.781990Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T19:46:54.782026Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:46:54.782060Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_UPGRADABLE(SU) 2017-08-03T19:46:54.782096Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:46:54.782175Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T19:46:54.803898Z 3 [Note] (upgrade_shared_lock)THIS MDL LOCK will upgrade2017-08-03T19:46:54.804201Z 3 [Note] (upgrade_shared_lock)THIS MDL LOCK upgrade TO2017-08-03T19:46:54.804240Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T19:46:54.804254Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:46:54.804267Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T19:46:54.804280Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:46:54.804293Z 3 [Note] (----->MDL PRINT) Mdl type :MDL_EXCLUSIVE(X) 2017-08-03T19:46:54.804306Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:46:54.804319Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T19:46:54.855563Z 3 [Note] (downgrade_lock)THIS MDL LOCK will downgrade2017-08-03T19:46:54.855693Z 3 [Note] (downgrade_lock) to this MDL lock2017-08-03T19:46:54.855706Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T19:46:54.855717Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:46:54.856053Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T19:46:54.856069Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:46:54.856082Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_UPGRADABLE(SU) 2017-08-03T19:46:54.856094Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:46:54.856214Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T19:47:00.260166Z 3 [Note] (upgrade_shared_lock)THIS MDL LOCK will upgrade2017-08-03T19:47:00.304057Z 3 [Note] (upgrade_shared_lock)THIS MDL LOCK upgrade TO2017-08-03T19:47:00.304090Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T19:47:00.304105Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:47:00.304119Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T19:47:00.304132Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:47:00.304181Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_EXCLUSIVE(X) 2017-08-03T19:47:00.304196Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:47:00.304211Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T19:47:01.032329Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok! 

首先獲得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) 

 

因為不管如何這個alter操作還是比較費時的,從時間我們看到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操作堵塞一切操作,基本對于這個TABLE的表全部堵塞。而對于ALGORITHM=COPY 其他部分差不多,但是在COPY階段用的是SNW鎖,接下來我就先來看看SNW鎖

8、MDL_SHARED_NO_WRITE(SNW)

SU可以升級為SNW而SNW可以升級為X,如前面所提及用于ALGORITHM=COPY 中,保護數據的一致性。
先看看它的兼容性

   Request | Granted requests for lock              type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   SNW    | +  +  +  -  -  -  +  -  -  - |

可以看到SR可以但是SW不行,當然也就堵塞了DML(SW)而SELECT(SR)不會堵塞,下面我只是給出了關鍵部分

mysql> alter table testsort12 add column ik int not null, ALGORITHM=COPY ;2017-08-03T20:07:58.413215Z 3 [Note] (upgrade_shared_lock)THIS MDL LOCK upgrade TO2017-08-03T20:07:58.413241Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T20:07:58.413257Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T20:07:58.413273Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T20:07:58.413292Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T20:07:58.413308Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_NO_WRITE(SNW) 2017-08-03T20:07:58.413325Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T20:07:58.413341Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T20:08:25.392006Z 3 [Note] (upgrade_shared_lock)THIS MDL LOCK upgrade TO2017-08-03T20:08:25.392024Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T20:08:25.392086Z 3 [Note] (->MDL PRINT) 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 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T20:08:25.392214Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_EXCLUSIVE(X) 2017-08-03T20:08:25.392228Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T20:08:25.392242Z 3 [Note] (------->MDL PRINT) Mdl status is: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 語句

兼容性如下

    Request | Granted requests for lock         |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   SRO    | +  +  +  -  -  +  +  +  -  - |堵塞DML(SW)但是SELECT(SR)還是可以的。mysql> lock table testsort12 read;Query OK, 0 rows affected (0.01 sec)2017-08-03T21:08:27.267947Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T21:08:27.267979Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T21:08:27.268009Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T21:08:27.268040Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T21:08:27.268070Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T21:08:27.268113Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO) 2017-08-03T21:08:27.268145Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T21:08:27.268175Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

10、MDL_SHARED_NO_READ_WRITE(SNRW)

用于LOCK TABLES WRITE語句

兼容性:

    Request | Granted requests for lock         |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   SNRW   | +  +  -  -  -  -  -  -  -  - |

可以看到DML(SW)和SELECT(SR)都被堵塞只有SH還可以,還可以DESC(SH) 。

mysql> lock table testsort12 write;Query OK, 0 rows affected (0.00 sec)2017-08-03T21:13:07.113347Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T21:13:07.113407Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T21:13:07.113435Z 3 [Note] (--->MDL PRINT) Namespace is:GLOBAL 2017-08-03T21:13:07.113458Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T21:13:07.113482Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T21:13:07.113505Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_STATEMENT 2017-08-03T21:13:07.113604Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T21:13:07.113637Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T21:13:07.113660Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T21:13:07.113681Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T21:13:07.113703Z 3 [Note] (-->MDL PRINT) OBJ_name is: 2017-08-03T21:13:07.113725Z 3 [Note] (--->MDL PRINT) Namespace is:SCHEMA 2017-08-03T21:13:07.113746Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)2017-08-03T21:13:07.113768Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T21:13:07.113791Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T21:13:07.113813Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 2017-08-03T21:13:07.113842Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!2017-08-03T21:13:07.113865Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T21:13:07.113887Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T21:13:07.113922Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T21:13:07.113945Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T21:13:07.113975Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_NO_READ_WRITE(SNRW) 2017-08-03T21:13:07.113998Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T21:13:07.114021Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

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

11、MDL_EXCLUSIVE(X)

用于各種DDL操作,注釋為CREATE/DROP/RENAME TABLE操作,實際上基本全部的DDL都會涉及到這個鎖,如上面分析的
add column操作,但是持續時間一般比較短暫。

兼容性:

   Request | Granted requests for lock         |    type  | S SH SR SW SWLP SU SRO SNW SNRW X |   ----------+---------------------------------------------+   X     | -  -  -  -  -  -  -  -  -  - |

沒有上面意外堵塞一切,也被一切所堵塞

比如剛才的add column操作

2017-08-03T19:46:54.804240Z 3 [Note] (>MDL PRINT) Thread id is 3: 2017-08-03T19:46:54.804254Z 3 [Note] (->MDL PRINT) DB_name is:test 2017-08-03T19:46:54.804267Z 3 [Note] (-->MDL PRINT) OBJ_name is:testsort12 2017-08-03T19:46:54.804280Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 2017-08-03T19:46:54.804293Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_EXCLUSIVE(X) 2017-08-03T19:46:54.804306Z 3 [Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION 2017-08-03T19:46:54.804319Z 3 [Note] (------->MDL PRINT) Mdl status is:EMPTY 

六、源碼注釋部分

enum enum_mdl_type { /*  An intention exclusive metadata lock. Used only for scoped locks.  Owner of this type of lock can acquire upgradable exclusive locks on  individual objects.  Compatible with other IX locks, but is incompatible with scoped S and  X locks. */ MDL_INTENTION_EXCLUSIVE= 0, /*  A shared metadata lock.  To be used in cases when we are interested in object metadata only  and there is no intention to access object data (e.g. for stored  routines or during preparing prepared statements).  We also mis-use this type of lock for open HANDLERs, since lock  acquired by this statement has to be compatible with lock acquired  by LOCK TABLES ... WRITE statement, i.e. SNRW (We can't get by by  acquiring S lock at HANDLER ... OPEN time and upgrading it to SR  lock for HANDLER ... READ as it doesn't solve problem with need  to abort DML statements which wait on table level lock while having  open HANDLER in the same connection).  To avoid deadlock which may occur when SNRW lock is being upgraded to  X lock for table on which there is an active S lock which is owned by  thread which waits in its turn for table-level lock owned by thread  performing upgrade we have to use thr_abort_locks_for_thread()  facility in such situation.  This problem does not arise for locks on stored routines as we don't  use SNRW locks for them. It also does not arise when S locks are used  during PREPARE calls as table-level locks are not acquired in this  case. */ MDL_SHARED, /*  A high priority shared metadata lock.  Used for cases when there is no intention to access object data (i.e.  data in the table).  "High priority" means that, unlike other shared locks, it is granted  ignoring pending requests for exclusive locks. Intended for use in  cases when we only need to access metadata and not data, e.g. when  filling an INFORMATION_SCHEMA table.  Since SH lock is compatible with SNRW lock, the connection that  holds SH lock lock should not try to acquire any kind of table-level  or row-level lock, as this can lead to a deadlock. Moreover, after  acquiring SH lock, the connection should not wait for any other  resource, as it might cause starvation for X locks and a potential  deadlock during upgrade of SNW or SNRW to X lock (e.g. if the  upgrading connection holds the resource that is being waited for). */ MDL_SHARED_HIGH_PRIO, /*  A shared metadata lock for cases when there is an intention to read data  from table.  A connection holding this kind of lock can read table metadata and read  table data (after acquiring appropriate table and row-level locks).  This means that one can only acquire TL_READ, TL_READ_NO_INSERT, and  similar table-level locks on table if one holds SR MDL lock on it.  To be used for tables in SELECTs, subqueries, and LOCK TABLE ... READ  statements. */ MDL_SHARED_READ, /*  A shared metadata lock for cases when there is an intention to modify  (and not just read) data in the table.  A connection holding SW lock can read table metadata and modify or read  table data (after acquiring appropriate table and row-level locks).  To be used for tables to be modified by INSERT, UPDATE, DELETE  statements, but not LOCK TABLE ... WRITE or DDL). Also taken by  SELECT ... FOR UPDATE. */ MDL_SHARED_WRITE, /*  A version of MDL_SHARED_WRITE lock which has lower priority than  MDL_SHARED_READ_ONLY locks. Used by DML statements modifying  tables and using the LOW_PRIORITY clause. */ MDL_SHARED_WRITE_LOW_PRIO, /*  An upgradable shared metadata lock which allows concurrent updates and  reads of table data.  A connection holding this kind of lock can read table metadata and read  table data. It should not modify data as this lock is compatible with  SRO locks.  Can be upgraded to SNW, SNRW and X locks. Once SU lock is upgraded to X  or SNRW lock data modification can happen freely.  To be used for the first phase of ALTER TABLE. */ MDL_SHARED_UPGRADABLE, /*  A shared metadata lock for cases when we need to read data from table  and block all concurrent modifications to it (for both data and metadata).  Used by LOCK TABLES READ statement. */ MDL_SHARED_READ_ONLY, /*  An upgradable shared metadata lock which blocks all attempts to update  table data, allowing reads.  A connection holding this kind of lock can read table metadata and read  table data.  Can be upgraded to X metadata lock.  Note, that since this type of lock is not compatible with SNRW or SW  lock types, acquiring appropriate engine-level locks for reading  (TL_READ* for MyISAM, shared row locks in InnoDB) should be  contention-free.  To be used for the first phase of ALTER TABLE, when copying data between  tables, to allow concurrent SELECTs from the table, but not UPDATEs. */ MDL_SHARED_NO_WRITE, /*  An upgradable shared metadata lock which allows other connections  to access table metadata, but not data.  It blocks all attempts to read or update table data, while allowing  INFORMATION_SCHEMA and SHOW queries.  A connection holding this kind of lock can read table metadata modify and  read table data.  Can be upgraded to X metadata lock.  To be used for LOCK TABLES WRITE statement.  Not compatible with any other lock type except S and SH. */ MDL_SHARED_NO_READ_WRITE, /*  An exclusive metadata lock.  A connection holding this lock can modify both table's metadata and data.  No other type of metadata lock can be granted while this lock is held.  To be used for CREATE/DROP/RENAME TABLE statements and for execution of  certain phases of other DDL statements. */ MDL_EXCLUSIVE, /* This should be the last !!! */ MDL_TYPE_END};/** Duration of metadata lock. */enum enum_mdl_duration { /**  Locks with statement duration are automatically released at the end  of statement or transaction. */ MDL_STATEMENT= 0, /**  Locks with transaction duration are automatically released at the end  of transaction. */ MDL_TRANSACTION, /**  Locks with explicit duration survive the end of statement and transaction.  They have to be released explicitly by calling MDL_context::release_lock(). */ MDL_EXPLICIT, /* This should be the last ! */ MDL_DURATION_END };/**  Object namespaces.  Sic: when adding a new member to this enum make sure to  update m_namespace_to_wait_state_name array in mdl.  Different types of objects exist in different namespaces   - GLOBAL is used for the global read lock.   - TABLESPACE is for tablespaces.   - SCHEMA is for schemas (aka databases).   - TABLE is for tables and views.   - FUNCTION is for stored functions.   - PROCEDURE is for stored procedures.   - TRIGGER is for triggers.   - EVENT is for event scheduler events.   - COMMIT is for enabling the global read lock to block commits.   - USER_LEVEL_LOCK is for user-level locks.   - LOCKING_SERVICE is for the name plugin RW-lock service  Note that although there isn't metadata locking on triggers,  it's necessary to have a separate namespace for them since  MDL_key is also used outside of the MDL subsystem.  Also note that requests waiting for user-level locks get special  treatment - waiting is aborted if connection to client is lost. */ enum enum_mdl_namespace { GLOBAL=0,              TABLESPACE,              SCHEMA,              TABLE,              FUNCTION,              PROCEDURE,              TRIGGER,              EVENT,              COMMIT,              USER_LEVEL_LOCK,              LOCKING_SERVICE,              BACKUP,              BINLOG,              /* This should be the last ! */              NAMESPACE_END };


注:相關教程知識閱讀請移步到MYSQL教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
国产在线二区| 韩国v欧美v日本v亚洲| 午夜伦欧美伦电影理论片| 一区二区精品免费| 欧洲精品久久久| 91精品久久久久久蜜臀| 亚洲一区激情| 国内精品99| 欧美亚洲国产日韩| 欧美日韩中文| 在线不卡日本| 久久精品日韩无码| 欧美日韩中国免费专区在线看| 日韩欧美久久久| 精品播放一区二区| 久久久久久久久99精品| 精品久久香蕉国产线看观看gif| 精品一二三四| 亚洲欧美中文字幕在线一区| 精品久久久久久综合日本欧美| 国产成人一区二区精品非洲| 一二三区精品视频| 欧美日韩中文国产| 91日韩中文字幕| 国产精品福利视频一区二区三区| 在线手机中文字幕| 亚洲素人一区二区| 久久视频免费看| 日韩国产欧美在线视频| 欧美日韩精品在线观看| 久久视频免费看| 亚洲热线99精品视频| 国产日韩成人精品| 国产黄在线看| 亚洲欧洲日韩在线| 亚洲天堂国产视频| 中文字幕日韩高清| 91精品蜜臀在线一区尤物| 国产三级第一页| 中文字幕在线观看国产| 国产高清视频一区二区| 偷窥国产亚洲免费视频| 欧美一级欧美三级在线观看| a√免费观看在线网址www| 国产欧美日韩中文久久| 欧美乱大交xxxxx免费| 欧美日韩国产页| 日韩视频一区在线观看| a视频免费看| 日韩美女中文字幕| 色一区在线观看| 日韩视频在线一区二区| 91最新在线| 日韩欧美亚洲国产| 欧美日韩乱国产| 日韩欧美亚洲国产一区| 日本国产一区| 亚洲最新永久观看在线| 99久久精品国产亚洲| 中文字幕99| 国产日韩中文在线| 国产欧美中文字幕| 日本熟女一区二区| 国产欧美日韩精品综合| 日韩精品欧美| 欧美不卡视频一区| 欧美日韩国产高清一区| 91精品无人成人www| 深夜福利一区二区| 亚洲免费看av| 欧美日本精品| 国产成人一二三区| 狠狠色综合色区| xxxcom在线观看| 日韩精品高清不卡| 亚洲二区自拍| 天堂在线视频中文网| 日韩精品首页| 亚洲最新免费视频| 天堂在线www天堂中文在线| av免费看在线| 一本一道综合狠狠老| 久久精品黄色片| 不卡一区2区| 日韩一级在线免费观看| 亚洲热在线观看| 欧美激情一区二区在线| 精品欧美日韩| 日韩精品在线免费观看| 精品日韩在线播放| 日韩精品中文在线观看| av免费观看国产| 国产免费一级| 91精品国产91久久久久久久久| 国产一级免费在线观看| 亚洲娇小xxxx欧美娇小| 91欧美在线视频| 偷窥国产亚洲免费视频| 国产日韩电影| 日韩中文字幕视频在线观看| 亚洲午夜久久| www.狠狠| www.狠狠干| 国产福利一区二区| 日韩免费电影网站| 国产三级精品在线观看| 久久蜜桃一区二区| 日韩欧美在线字幕| 精品久久久久久综合日本欧美| 国产极品嫩模在线视频一区| 国产欧美日韩视频| 91精品国产亚洲| 91精品国产综合久久精品app| av首页在线| 国产激情在线| 精品一性一色一乱农村| 大香一本蕉伊线亚洲网| 欧美日韩高清在线一区| 91精品国产综合久久久久| 精品国产31久久久久久| 国产v日产∨综合v精品视频| 亚洲福利视频在线| 中文在线一区二区| 91精品国产手机| 国产视频不卡| 黄色片免费看| 视频一区二区精品的福利| 精品久久蜜桃| 最近中文字幕第一页| 国产黄色高清在线| 在线亚洲免费| 欧美日韩精品是欧美日韩精品| 欧美日韩一级片在线观看| 日韩欧美一二三区| 欧美日韩国产系列| 国产成人精品av久久| 精品亚洲综合| 婷婷久久综合九色国产成人| 国产欧美日韩最新| 亚洲一区二区三区精品中文字幕| 日韩精品视频在线看| 一区二区三区精品在线观看| 国产欧美日韩中文| 日韩影院二区| 国产在线视频不卡| 欧美日韩视频不卡| 黄色国产网站在线观看| 成人久久久久| 日韩在线中文字幕| 欧美大片在线观看一区| 久久久水蜜桃| 日韩视频1区| 日韩免费视频一区二区视频在线观看| 91精品国产综合久久久蜜臀粉嫩| 日韩在线不卡| 欧美日韩国产专区| 在线视频1区2区| 黄色一区二区在线| av一区在线观看| 91www成人久久| 日本中文字幕在线观看| 国产字幕在线看| 日韩欧美国产亚洲| 日韩欧美在线字幕| 深夜日韩欧美| 香蕉人人精品| 久久riav| 欧美日韩国产一二三| 国产1卡2卡三卡四卡网站| 91精品国产自产观看在线| 亚洲高清视频一区| 欧美日韩精品电影| 色综合婷婷久久| 精品国产免费视频| 日韩欧美中文免费| 欧美日韩高清在线播放| 亚洲一区在线观看免费| 日韩欧美综合在线| 久久av免费| 国产福利第一页| 视频一区视频二区中文| 91麻豆精品国产91久久久使用方法 | 精品国产乱码久久久久久蜜臀| 欧美自拍一区| а√天堂8资源中文在线| 欧美日韩国产999| 欧美日韩999| 欧美在线视频第一页| 中文字幕日韩精品在线| 精品视频—区二区三区免费| 亚洲欧洲国产视频| 亚洲3区在线| 日韩av一区二区在线观看| 欧美日韩国产综合视频在线观看中文 | 欧美在线视频二区| 国产中文在线观看| 亚洲综合日韩| 91精品国产综合久久久久久| 欧美日韩精品免费在线观看视频 | 日韩亚洲欧美中文在线| 日韩在线视频免费观看高清中文| 国产欧美日韩最新| 亚洲一级二级| 日韩精品手机在线观看| 91精品国产调教在线观看| 91精品国产自产观看在线| 欧美日韩精品欧美日韩精品 | 麻豆精品99| 极品久久久久久| 中文精品在线观看| 日韩欧美中文第一页| 欧美中文字幕视频| 亚洲第一中文字幕| 日韩在线视频免费观看| 国产一区久久久| 国产一级免费| 内射国产内射夫妻免费频道| 91久久精品网| 亚洲午夜91| 日韩在线一区二区视频| 亚洲免费视频一区| 亚洲第一页中文字幕| 日本不卡视频一区| 欧美 日韩 国产 在线观看| 亚洲欧洲一区二区天堂久久| 中文字幕在线播出| 一区三区二区视频| 国产一卡2卡3卡免费网站| 日韩欧美国产黄色| 免费看日韩精品| 日本a级黄色| 国产三级精品在线观看| 欧美日韩精品电影| 欧美日韩精品三区| 91精品国产综合久久久久| 亚洲区中文字幕| 精品日韩一区二区三区免费视频| 亚洲欧美小说国产图片| 国产日韩中文字幕| 亚洲乱码在线观看| 日韩在线欧美| 精品区一区二区| 一区二区三区在线免费| 亚洲欧洲日产国码av系列天堂| 91精品日本| 日韩一级二级三级精品视频| 91精品国产综合久久久久| 日韩欧美不卡在线| 中文字幕日韩国产| 不卡一二三区| 国产真实乱子伦精品视频| 国产一区三区三区| 91久久精品在线| 第一页在线观看| 高清不卡一区二区| www.老鸭窝.com| 久久久99免费| 欧美熟妇乱码在线一区| a√免费观看在线网址www| 日韩欧美国产成人一区二区| 午夜影院在线观看欧美| 国产一级片播放| 日韩精品资源二区在线| 欧美久久在线观看| 中文在线日韩| 日韩黄色在线播放| 久久久综合精品| 中文官网资源新版中文第二页在线观看| 日韩一级精品| 中文字幕日韩第一页| 日韩精品视频免费在线观看| 一区二区高清视频| 中文字幕精品在线| 国产一卡2卡3卡4卡网站免费| 91精品视频观看| 日韩欧美在线精品| 在线看av的网址| 国产福利第一页| 日韩中文字幕在线视频播放| 精品视频1区2区3区| 日本精品专区| 香蕉av一区| 国产福利免费观看| eeuss一区| 国产黄在线看| 国产三级在线播放| 国产日韩在线亚洲字幕中文| 欧美日韩国产123区| 欧美日韩午夜在线视频| 国产91久久久久蜜臀青青天草二| 国产伦精品免费视频| 日韩欧美国产黄色| 欧美日韩国产首页在线观看| 亚洲欧洲综合另类| 欧美日韩久久久| 国产真实乱子伦精品视频| 中文字幕国产日韩| 中文字幕亚洲在| 日韩美女中文字幕| 国产成人精品av久久| 中文 欧美 日韩| 精品三级久久| 亚洲一区在线观看免费| 日韩精品视频在线观看网址| 成人禁用看黄a在线| 欧美日韩精品在线 | 国产不卡一区| 一区二区三区中文字幕在线观看| 午夜影院在线观看欧美| 欧美日韩精品综合| 激情国产在线| 久久福利视频一区二区| 国产三级中文字幕| 欧美日韩国产综合网| 欧美高清一级片在线| 午夜福利一区二区三区| 国产丝袜在线播放| 蜜臀国产一区| 亚洲影视资源网| 国产蜜臀在线| 日韩欧美在线网址| 欧美日韩国产999| 亚洲视频电影在线| 日韩精品在线中文字幕| www.三级.com| 91精品国产综合久久精品| av三级在线播放| 91精品在线免费| 在线资源av| 精品国产欧美日韩不卡在线观看| 欧美一级手机免费观看片| 在线欧美日韩国产| 午夜一区二区视频| 亚洲一区在线观看网站| 天天摸日日摸狠狠添| 婷婷久久综合九色国产成人| 亚洲成av人片一区二区密柚| 91精品国产99| 日韩视频一区在线观看| 日韩在线不卡一区| 不卡一区二区三区视频| 国产美女主播视频一区| 欧美xxxx中国| 中文字幕第一页在线播放| 国产一二三精品| 亚欧成人精品| 亚洲3区在线| 91九色在线播放| 亚亚洲欧洲精品| 国产免费永久在线观看| 日韩高清在线一区二区| 久久99久久99精品中文字幕| 日韩欧美国产网站| 欧美日韩亚洲91| 精品婷婷伊人一区三区三| 一区二区三区中文字幕在线观看| 亚洲成年人影院在线| 亚洲福利在线观看| 欧美日韩色综合| 日韩久久精品成人| 亚洲免费观看在线观看| 91久久精品视频| 亚洲伊人婷婷| 黄色在线播放网站| 日韩午夜黄色| 亚洲va中文字幕| 日本熟女一区二区| 91一区二区| 91久久精品网| 日韩中文字幕精品视频| www.老鸭窝.com| 精品午夜av| av免费观看国产| 日本亚洲欧美| av一区二区高清| 欧美日韩一级视频| 精品久久久三级| 成年人黄国产| 日韩一级二级三级| 久久91精品视频| 精品久久久视频| 在线国产1区| 欧美三级日本三级少妇99| 日韩欧美中文字幕视频| av一区二区高清| 久久精品久久精品亚洲人| 日韩精品不卡一区二区| 欧美日韩夫妻久久| 日韩国产成人| 一本一道综合狠狠老| av免费不卡国产观看| 91精品在线观看入口| 欧美日韩性视频一区二区三区 | 欧美日韩中文字幕综合视频| 极品久久久久久| 欧美日韩精品三区| 91精品国产自产在线丝袜啪| 天天综合天天添夜夜添狠狠添| 国产综合成人久久大片91 | 久久福利视频一区二区|