mysql 有兩個視圖記錄 metadata_lock 相關 的信息:
performance_schema.metadata_locks
sys.schema_table_lock_waits
但是默認是情況下,即使出現了 Waiting for table metadata lock ,兩個視圖裏面也沒有任何的記錄 。
如果想在兩個視圖中看到相關信息,需要啓用相關的設置:
primary:performance_schema 11:38:34>update setup_consumers set enabled='YES' where name ='global_instrumentation';
Query OK, 0 rows affected (0.01 sec)
Rows matched: 1 Changed: 0 Warnings: 0
primary:performance_schema 11:40:28>update setup_instruments set enabled='YES' where name='wait/lock/metadata/sql/mdl';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
下面我們用一個案例來進行分析:
session 1 | session 2 |
begin; select * from hlb limit 1; |
|
alter table hlb add cxx int; |
該視圖記錄的是被阻塞會話的信息,因此我們需要 kill 9 來rollback 會話 9 。
primary:performance_schema 11:57:32>SELECT * from sys.schema_table_lock_waits\G
*************************** 1. row ***************************
object_schema: bak
object_name: hlb
waiting_thread_id: 31 --等待的線程ID
waiting_pid: 6 --等待的連接PID
waiting_account: root@localhost
waiting_lock_type: EXCLUSIVE --等待的鎖類型
waiting_lock_duration: TRANSACTION
waiting_query: alter table bak.hlb add cxxx int
waiting_query_secs: 4 --鎖等待時間
waiting_query_rows_affected: 0
waiting_query_rows_examined: 0
blocking_thread_id: 31
blocking_pid: 6
blocking_account: root@localhost
blocking_lock_type: SHARED_UPGRADABLE --等待的鎖類型
blocking_lock_duration: TRANSACTION
sql_kill_blocking_query: KILL QUERY 6
sql_kill_blocking_connection: KILL 6
*************************** 2. row ***************************
object_schema: bak
object_name: hlb
waiting_thread_id: 31
waiting_pid: 6
waiting_account: root@localhost
waiting_lock_type: EXCLUSIVE
waiting_lock_duration: TRANSACTION
waiting_query: alter table bak.hlb add cxxx int
waiting_query_secs: 4
waiting_query_rows_affected: 0
waiting_query_rows_examined: 0
blocking_thread_id: 34
blocking_pid: 9
blocking_account: root@localhost
blocking_lock_type: SHARED_READ
blocking_lock_duration: TRANSACTION
sql_kill_blocking_query: KILL QUERY 9
sql_kill_blocking_connection: KILL 9
2 rows in set (0.01 sec)
另外MDL 是在mysql server 層的鎖,而innodb 層也有表級別上的鎖(IS/IX),但兩者並不是一回事
MDL 鎖等待超時閾值 由選項 lock_wait_timeout 控制,默認值是一年,我們可以將它調低