天天看點

MySQL · 捉蟲動态 · 5.7 mysql_upgrade 中繼資料鎖等待

如下圖,mysql_upgrade 過程中,執行 drop database if exists performance_schema 一直在等待 metadata lock

MySQL · 捉蟲動态 · 5.7 mysql_upgrade 中繼資料鎖等待

有一種簡單的解決方法,把其他連接配接kill掉,釋放 metadata lock

對于這個案例,占用中繼資料鎖的是 id = 107768,user = xx1 的連接配接

但是這種方法名額不治本,案例中占用中繼資料鎖的連接配接,是一個agent服務建立的

mysql_upgrade也是程式執行,不能每次都手工kill連接配接,需要查明為什麼占用鎖

據業務方回報,agent服務和調用mysql_upgrade的代碼和5.6也在用,沒有出現問題。

懷疑是5.7引入的bug

根據上述現象,顯然是agent占了metadata lock,大機率不是mysql的bug

為了說服業務方,我們繼續排查是在等待什麼鎖

首先想到5.7的 performance_schema.metadata_locks ,很遺憾這張表裡并沒有記錄

MySQL · 捉蟲動态 · 5.7 mysql_upgrade 中繼資料鎖等待

我們嘗試使用 gdb 擷取鎖等待資訊

<code>ps aux | grep 端口号</code>,找出mysqld程序号 pid,<code>pstack pid &gt; stack.log</code>

在stack.log中搜尋 acquire_lock(請求mdl鎖的函數),可以看出是 thread 3 在請求中繼資料鎖

MySQL · 捉蟲動态 · 5.7 mysql_upgrade 中繼資料鎖等待

上述資訊可以看出,正在請求performance_schema.global_status這張表的鎖

和業務方确認,agent中确實執行了 “show global status” , 但是已經設定了autocommit

簡化邏輯後,agent代碼如下

代碼中确實設定了autocommit,但是并沒有生效(如果執行了commit,不可能不釋放中繼資料鎖)

mysqldb.connect 傳回 connection 類,根據上述代碼,autocommit是 connection的成員屬性

connection 繼承自_mysql.connection,_mysql 是c語言實作的python庫,檢視_mysql.c

autommit 并不是成員屬性,而是一個成員方法

conn.autocommit = true 強行将 autocommit 的函數指針指派為 true,并沒有真正設定autocommit

5.6中沒有發現這個問題

一是 agent 中隻有查詢語句,不設autocommit也能傳回查詢結果

二是 5.6中 “show global status” 查詢的是 information_shcema,5.7中是performance_schema,5.6中不會影響 drop database performance_schema

繼續閱讀