1. 程式人生 > >Mysql DDL出現長時間等待MDL問題分析

Mysql DDL出現長時間等待MDL問題分析

開發十年,就只剩下這套架構體系了! >>>   

給表新增欄位時,發現鎖表了,檢視程序,提示Waiting for table metadata lock,等待鎖釋放;然而蛋疼的是幾分鐘過去了,依然沒有任何的進展,特此記錄下這個問題的定位過程以及MDL的相關背景知識

看到上面的表現,基本問題就來了

  • Metadata Lock 是什麼鬼
  • 是什麼原因導致一直等待

<!-- more -->

I. 問題定位

首先需要確認什麼地方加鎖,從mysql出發,應該怎麼定位?

1. 定位過程

對於mysql而言,一般來講上鎖和事物時伴生關係,所以我們的直觀出發點就是查詢db當前正在執行的事物

-- 查詢當前正在執行的事物的sql
SELECT * FROM information_schema.INNODB_TRX;

輸出結果如下,首先拿到事物對應的程序id

拿到id之後,則可以分析對應的程序資訊

-- 查詢程序資訊
show processlist

-- 查詢所有的程序資訊
show full processlist

然後定位到具體的程序

然後登陸到目標機器,檢視埠號對應的程序,通過lsof

命令檢視

lsof -i tcp:52951

從圖中可以看出,是一個python程序的mysql連線開啟的事物,程序id為5436

接著檢視程序對應的資訊

ps aux | grep 5436

這個指令碼正是測試aiomysql的python指令碼,內容比較簡單

import asyncio
import aiomysql

loop = asyncio.get_event_loop()


@asyncio.coroutine
def test_example():
    conn = yield from aiomysql.connect(host='127.0.0.1', port=3306,
                                       user='root', password='', db='test',
                                       loop=loop, autocommit=False)

    cur = yield from conn.cursor()
    yield from cur.execute("SELECT * from test_table")
    print(cur.description)
    r = yield from cur.fetchall()
    print(r)
    yield from cur.close()
    conn.close()

loop.run_until_complete(test_example())

2. 原因分析

對python不太熟,直接藉助google查一下,發現有同樣的問題

這個問題丟擲,在通過with開啟連接獲取遊標後,執行mysql,但是沒有commit之前,會鎖表,這個期間修改表都會出現等待

下面近給出瞭解答,並沒有看到更多的深層次的說明,先記錄下,解決辦法就是在建立連線池的時候,選擇自動提交方式,然後就不會有這個問題了

pool = await aiomysql.create_pool(
    host="localhost",
    user="test",
    password="test",
    db="test",
    autocommit=True,
    cursorclass=DictCursor,
    loop=loop)

II. Metadata Lock說明

找到一篇文章說MDL的,推薦詳細閱讀 MySQL表結構變更你不可不知的Metadata Lock詳解

1. MDL 說明

抓一下核心的要點,簡單說一下看完這篇文章之後的樸素理解

MetaData Lock 簡稱為MDL,簡單來說就是表的元資料鎖;當修改表結構的時候,就需要持有這個鎖

a. 作用

MDL的主要作用只有一點,保護一個正在執行的事物表結構不被修改

有一個原則,MDL是事物級別的,只有事物結束之後才會釋放,而這裡面說的事物分為兩類

  • 顯示事物:
    • 關閉autocommit
    • 以begin或start transaction開始的操作
  • AC-NL-RO(auto-commit non-locking read-only):
    • auto commit 開啟之下的select操作

b. 例項說明

直接看上面的說明,不太直觀,一個經典的case如下

session1 開啟了一個事物,執行查詢操作;但是現在session2 要刪除表,如果執行成功,那麼session1的第二次查詢就跪了,這樣就違背了事物的原則,所有在5.5版本引入了MDL,來保證在事物執行期間,表結構不被修改

2. 出現MDL等待原因及解決方法

當我們出現修改表結構,就需要獲取MDL的排他鎖,因此只有這個表沒有事物在執行時,才能獲取成功;當持有獨佔鎖之後,這個表的其他操作將被阻塞(即不能插入資料,修改資料,也不能開啟事物操作)

因此在執行DDL時,一直出現等待MDL的時候,常見的原因有下面三個

a. 長事物,阻塞DDL,從而阻塞所有同表的後續操作

通過 show processlist看到表上有正在進行的操作(包括讀),此時修改表時也會等待獲取MDL,這種時候解決辦法要麼就是等待執行完畢,要麼就是直接kill掉程序

b. 未提交事物,阻塞DDL

通過 show processlist沒有找到表上的操作,但是通過information_schema.innodb_trx發現有未提交的事物,

c. 異常的狀況

通過 show processlist 和事物查詢都沒有的情況下,可能的場景是一個顯示的事物中,對錶的操作出現了異常,雖然事物失敗,但是持有的鎖還沒有釋放,也會導致這個原因

可以在performance_schema.events_statements_current表中查詢失敗的語句

3. MDL分類與sql例項

前面兩小節,分別說明什麼是MDL(樸素理解為表的元資料鎖),以及當修改表時出現長時間的等待MDL的原因分析;正常看完之後,應該會有下面的疑惑

  • MDL有哪些型別
  • 哪些sql會持有MDL

對於MDL的型別,從網上截一張圖

接下來需要分析下不同鎖模式對應的sql

屬性含義事例
MDL_INTENTION_EXCLUSIVE(IX)意向排他鎖用於global和commit的加鎖。truncate table t1; insert into t1 values(3,’abcde’); 會加如下鎖 (GLOBAL,MDL_STATEMENT,MDL_INTENTION_EXCLUSIVE)(SCHEMA,MDL_TRANSACTION,MDL_INTENTION_EXCLUSIVE)
MDL_SHARED(S)只訪問元資料 比如表結構,不訪問資料。set golbal_read_only =on 加鎖 (GLOBAL,MDL_EXPLICIT,MDL_SHARED)
MDL_SHARED_HIGH_PRIO(SH)用於訪問information_scheam表,不涉及資料。select * from information_schema.tables;show create table xx; desc xxx; 會加如下鎖: (TABLE,MDL_TRANSACTION,MDL_SHARED_HIGH_PRIO)
MDL_SHARED_READ(SR)訪問表結構並且讀表資料select * from t1; lock table t1 read; 會加如下鎖: (TABLE,MDL_TRANSACTION,MDL_SHARE_READ)
MDL_SHARED_WRITE(SW)訪問表結構並且寫表資料insert/update/delete/select .. for update 會加如下鎖:(TABLE,MDL_TRANSACTION,MDL_SHARE_WRITE)
MDL_SHARED_UPGRADABLE(SU)是mysql5.6引入的新的metadata lock,可以說是為了online ddl 才引入的。特點是允許DML,防止DDL;alter table/create index/drop index 會加該鎖; 加入下鎖 (TABLE,MDL_TRANSACTION,MDL_SHARED_UPGRADABLE)
MDL_SHARED_NO_WRITE(SNW)可升級鎖,訪問表結構並且讀寫表資料,並且禁止其它事務寫。alter table t1 modify c bigint; (非onlineddl) (TABLE,MDL_TRANSACTION,MDL_SHARED_NO_WRITE)
MDL_SHARED_NO_READ_WRITE(SNRW)可升級鎖,訪問表結構並且讀寫表資料,並且禁止其它事務讀寫。lock table t1 write; 加鎖 (TABLE,MDL_TRANSACTION,MDL_SHARED_NO_READ_WRITE
MDL_EXCLUSIVE(X)防止其他執行緒讀寫元資料CREATE/DROP/RENAME TABLE,其他online DDL在rename階段也持有X鎖(TABLE,MDL_TRANSACTION,MDL_EXCLUSIVE)

4, 小結

上面的內容,可能資訊量比較大,特別是MDL的鎖分類情況,很難抓住重點,針對我們日常接觸中,簡單給出小結

  • MDL是為了保證事物執行過程中,表結構不被修改引入的;因此修改表結構的前提是這個表上沒有事物(沒有正在執行,失敗,或者未提交的事物)
  • DDL執行,一般來講是需要獲取排他的MDL
  • DML都會開啟事物,因此會獲取 MDL_SW
  • DQL語句會獲取 MDL_SR

幾個簡稱的說明

  • MDL: metadata lock,可以簡單理解為表的元資料鎖
  • DDL: 資料定義語言,可以簡單理解為表的操作,如建立,修改,刪除表、檢視等,新增索引、欄位等操作
  • DML: 資料操作語言,也就是我們常規理解的 insert, update, delete 語句
  • DQL: 資料查詢語言,常見的select語句

幾個常見疑問解答

a. 為什麼同一張表的多個DDL不能並行執行

  • MDL讀鎖是互相相容的,可以有多個增刪查改
  • MDL寫鎖是互斥的,只能有一個表的DDL

b. 為什麼有時候DDL會卡住

  • MDL讀寫鎖之間是互斥的,所以如果DDL卡住,就證明有事務在執行,不能申請MDL寫鎖

c. 常見卡住的場景

  • 非常頻繁的業務高峰期
  • 有慢查詢把持著MDL讀鎖
  • 有事物一直未提交

d. 為什麼需要MDL鎖

  • 當事務本身執行的時候理論上是不能容忍表結構在中途發生改變的

5. 更多參考

相關博文或者問答

II. 其他

1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛

2. 宣告

盡信書則不如,已上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

3. 掃描關注

一灰灰blog

QrCode

知識星球

相關推薦

Mysql DDL出現時間等待MDL問題分析

開發十年,就只剩下這套架構體系了! >>>   

Monkey出現SystemServer 記憶體佔用高達200MB以上,時間等待無降低

5臺手機有一臺保持在280M佔用沒有降下來,其他4臺都降到150M左右; 沒有降下來的手機其佔用增長,主要體現在java heap和native heap上面。 XXXX:/ # cat /d/ion/ion_mm_heap | grep Splash 0xc2552cc

mysql innodb引擎 時間使用後,資料檔案遠大於實際資料量,導致空間不足。

近期我碰到了一個令人頭疼的事情。就是我的mysql伺服器使用了很久之後,發現/data  目錄的空間佔滿了我係統的整個空間,馬上就要滿了。下面是我的分析。 在網上查看了這2個方法,但是執行後發現沒有解決。系統空間沒有變小。 1.optimize table table.n

php非同步實現,避免時間等待

處理的php非同步的方法有好幾種,這裡我就只介紹我經常用的而且官方也推薦的 廢話少說,直接貼程式碼//php非同步 public function doRequest($host,$path, $param=array()){ $query = i

cisco裝置避免輸錯命令後時間等待

避免輸錯密碼後出現以下情形的命令: (conf-t)#no ip domain-lookup 2960-M201A-S-20.133#cmddTranslating "cmdd"...domain server (255.255.255.255)% Unknown comma

解決Docker外掛安裝過程進入時間等待的問題

為了讓Jenkins實現Docker部署,需要安裝Jenkins的Docker外掛和docker-build-step外掛(必要性

解決windows xp 開機時出現“歡迎使用”等待時間

1.更改系統服務至使系統啟動變慢, 服務名稱:Event Log 解決方法,改回初始狀態 2.系統配置檔案過多.清理個人賬戶的配製檔案。X:\Documents and Settings\賬戶名\Application Data (可以試著排除這個原因,可以新建一個

MySQL管理時間運行查詢

長查詢1. 出現長時間執行的查詢的原因 由於SQL執行效率差而導致的長時間查詢: 由於被SQL註入而導致的長時間查詢: 由於DDL語句引起表元數據鎖等待:2. 長時間執行的查詢帶來的問題 通常來說,除非是BI/報表類查詢,否則長時間執行的查詢對於應用缺乏意義。 消耗系統資源,比如大量長

演算法 -- 四種方法獲取的最“迴文串”,並對時間複雜進行分析對比&PHP

迴文串: “迴文串”是一個正讀和反讀都一樣的字串,比如“level”或者“noon”等等就是迴文串。 -- 來自百度百科 關於獲取字串中最長的迴文串的演算法中,目前有很多演算法,本文中主要是用PHP來實現的演算法之一。 演算法一:暴力解法 暴力計算出所有的字串並判斷。時間複雜

MySQL資料庫有段時間沒有用了,今天使用出現了1067錯誤,程序意外終止。

對於1067錯誤,程序意外終止,系統錯誤。 我試了網上的很多方法,最終皆是失敗而歸,浪費快一天的時間,廢話少說,看解決方案。 解決方案:有位大佬讓我檢視windows日誌檔案,、然後我獲得錯誤資訊如下: InnoDB: Attempted to open a

jupyter notebook中出現ValueError: signal only works in main thread 報錯 即 時間in[*] 解決辦法

我在jupyter notebook中新建了一個基於py3.6的kernel用來進行tensorflow學習 但是在jupyter notebook中建立該kernel時,右上角總是顯示 服務正在啟動中,請稍候(kernel is starting,please wait)同時 kernel中顯示 in[

Python爬蟲時間出現SSL證書驗證問題

Python爬蟲長時間出現SSL證書驗證問題 今天做了一個爬蟲程式,執行好好的,但是執行2個小時之後突然報錯了,看了一下也不是IP原因,也不是程式碼邏輯問題。報錯資訊是 requests.exceptions.SSLError: ("bad handshake: Error([('SSL r

開機動畫片階段停留很時間並黑屏不進入launcher原因分析

hi3716c-android4.0.3SDK在開機動畫階段停留很長時間並黑屏不進入launcher原因分析最近基於海思3716c方案的智慧機頂盒批量出貨了,但出現了意想不到的問題。有少數機頂盒在開機動畫停留很長時間有5分鐘之多,之後黑屏,不進入Launcher,就像宕機了

Mysql+hibernate 時間不操作再進入,導致連線池關閉的問題解決。

最近總是發現自己的MySQL資料庫,隔天不登陸一次,就會出現以下錯誤: ERROR [2016-04-27 07:59:38] [http-bio-80-exec-10] org.hibernate.transaction.JDBCTransaction:95 - J

MySQL for mac 無法啟動的處理方法——我是時間未用了導致的

       由於我好長一段時間沒有使用MySql,去設定裡面啟動MySql時,突然啟動不了,點啟動沒的反映,輸入使用者密碼也是沒有反應的,我差點都想解除安裝了我的mysql重新裝了。 下面請看我給你們走秀一波。         上面顯示:  原因是某種情況下導致”/usr/

蘋果appstore稽核等待時間的解決方案

好多朋友最近這段時間,大概是從17年5月份以後,會碰到in review 很長時間不出結果的 碰到這種情況就是蘋果所謂的延期稽核了。delayed review  蘋果是故意這樣做的。大多情況是稽核員感覺你提交的應用是垃圾應用或者重複了之類的。 特別像是現在上線棋牌

mysql 時間佔用cpu資源的問題記錄

公司內部伺服器有一次例行top檢視 系統資源情況,發現mysqld程序嘗試處於 99% 當時感覺很奇怪,很擔心有什麼不合理的查詢一直掛著。 通過 show processlist 發現 通過 ps -ef |grep mysql 和 pstree

Android6.0以上應用在時間在後臺,因為記憶體不足導致系統回收記憶體,當再次啟動應用出現Fragment重疊或者空白、異常解決方案(提供模擬記憶體不足導致系統回收記憶體的方案)。

  Android6.0以上應用在長時間在後臺,因為記憶體不足導致系統回收記憶體,當再次啟動應用出現Fragment重疊或者空白解決方案。首先提供一個方法模擬記憶體不足導致系統回收記憶體的方案:開啟Android Studio -->Tools-->Android

MySQL 管理時間運行查詢

sch wait schedule shel mysq serve sub not in 管理 最常用的查詢 select concat (‘kill ‘,id,‘;‘) from information_schema.processlist where

Python3.7爬蟲 大量爬取某小說網站小說並寫入mysql(持續完善中...) 未解決問題:mysql時間新增超過百萬條數據表鎖甚至崩潰

oot req val page src sele 爬蟲 use uwa 練手之作 代碼中還有很多問題 持續完善中 渣渣阿裏T5 99包郵服務器只開了6個進程 #encoding:utf-8 import requests # 請求 from lxml import