發現一個關於MySQL的metadata lock的BUG

2021-02-21 資料庫隨筆

請進行以下操作實現復現: 

表結構如下:

mysql> create table xcy_test_utf8( id  int ,

    -> name varchar(2),

    -> addr varchar(200));

會話A:

mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> insert into xcy_test_utf8 values(1,'xcy','beijing');

ERROR 1406 (22001): Data too long for column 'name' at row 1

發現name欄位太短, 然後通知DBA或者自己進行修改。

會話B:

alter table  xcy_test_utf8  modify name varchar(30);

沒有馬上執行完成, 還以為是表太大,等等。。。。。。

已經過了一會兒了, 發現還沒有執行完,是不是不對勁?通過其他會話執行show processlist ,發現了 Waiting for table metadata lock.

為什麼會有 Waiting for table metadata lock 的現象?原因很簡單, 因為有事物沒有提交。嗯,確實如此,因為剛才執行了insert語句, 因為name列定義的長度太短,然後報錯了。  目前還沒有發起回滾命令 。 

但是,作為後臺的資料庫管理人員,怎麼去發現有未提交的事務?作者知道的手法如下:(如果有朋友知道更多方法,請留言)

方法1:show engine innodb status \G

沒有發現狀態為active(未提交) 的事務

方法二:查詢information_schema.innodb_trx 表

沒有發現有事務。

兩個方式都沒有發現活躍事務,但alter 語句卻被活活堵塞了。文章快寫完了,alter語句還在執行呢。 自然也會堵塞其他對這個表進行更新操作的會話,形成一個堵塞隊列。

如果是默認的lock_wait_timeout , alter 語句將在31536000 秒後鎖超時。

所以,如果發現您的alter 語句被莫名其妙的堵塞了,通過上面的方法還沒有發現是被誰堵塞了,就別慌了,也不用懷疑您自己的技能問題。

 

當前處理方法:

儘快取消或者kill執行alter語句的會話,以免造成堵塞隊列,影響系統的可用性。

如果alter語句必須現在就執行,通知應用管理人員後,通過show processlist 命令,找出所有狀態為Sleep的會話,然後全部殺掉。(一個一個殺也行,直到alter語句可以執行為止,但如果手工做,速度慢.)

  

    3.  另外,建議在執行alter語句之前,修改會話級lock_wait_timeout參數,例如設置10秒鐘,10秒鐘還沒有獲得metadata 鎖,將自動鎖超時, 以免長時間堵塞對這個表的dml操作。

     4.對於研發人員,執行sql失敗時,請一定儘快執行rollback命令。

猜測bug出現的原因:

        在執行SQL失敗後,沒有清理該SQL所獲取的metadata 鎖。 但如果修補的話,需要考慮mysql目前是半回滾機制,只回滾當前出錯的sql,而不是整個事務(整個事務回滾需要執行rollback命令),所以也不能在sql執行失敗時,就直接清理掉metadata 鎖,需要有個判斷機制。  

         因為在5.7.18上能夠100%的復現,後續將向官方提bug. 

  

相關焦點

  • MySQL 之 Metadata Locking 研究
    metadata lock 的作用就是當一個事務在執行時,事務涉及到的所有元數據(metadata,也就是 database objects),必須是安全的。比如你在一個事物中select一個table,必須保證該table在你的事物完成之前,她不會被刪除了,或者不會被修改了。
  • 究竟是哪個會話造成了"Waiting for table metadata lock"等待
    select * from xcy;通過show processlist 命令,查詢資料庫當前會話狀態:發現增加索引的會話出現了「Waiting for table metadata lock「等待,查詢語句"select * from xcy" 也出現同樣的等待,其他會話都是sleep 狀態。
  • 看來,MySQL next-key lock 的 bug 並沒有被修復!
    前言在上一篇文章《MySQL next-key lock 加鎖範圍是什麼?》next-key 的前開後閉區間,而 8.0.18 及以後版本,修復了這個 bug。腦袋炸裂呀,完全和主鍵索引的 next-key lock 加鎖範圍不同,人家 sql 是什麼就鎖什麼。有小夥伴知道原因可以告訴我。如果我把 sql 改成下面的這種呢?
  • 幾個常見而嚴重的 MySQL 問題分析 | 運維進階
    提示為:Waiting fortable metadata lock (show processlist中可查)。 2 原理詳細分析2.1 什麼是MDL鎖?為了在並發環境下維護表元數據的數據一致性,在表上有活動事務(顯式或隱式)的時候,不可以對元數據進行寫入操作。
  • mysqldump備份時的數據一致性問題
    原標題:mysqldump備份時的數據一致性問題作者:魏新平,知數堂優秀校友。在日常運維當中,經常會用到mysqldump。使用mysqldump導出數據的時候,我們最關心的問題之一就是表的一致性。簡單的說就是所有表是不是同一時間的數據和結構。
  • 來看看 MySQL 的這個 BUG,坑了多少人....
    因此,首先得懷疑是5.7內核出了問題,因此第一反應是從官方bug list中搜索一下是否有類似問題存在,避免重複造車。經過搜索,發現官方有1個類似的bug,這裡簡單介紹一下該bug。;同時設置當前handler要處理的下一個自增列的值。
  • MySQL Online DDL 原理和踩坑
    例如 Table 14.10 中顯示修改列的數據類型不支持 INPLACE這時嘗試將原類型為 FLOAT 的 column_name 改為 INT執行過程初始化:根據存儲引擎、用戶指定的操作、用戶指定的 ALGORITHM 和 LOCK 計算 DDL 過程中允許的並發量,這個過程中會獲取一個 shared metadata lock
  • MySQL鎖
    最近稍微有點忙,好久沒空去寫東西了,白天有個小夥伴問到一個問題,資料庫出現Waiting for table metadata lock鎖等待問題
  • MySQL慢查詢記錄原理和內容解析
    (Waiting for table metadata lock)MySQL層 MyISAM表鎖消耗的時間。(Waiting for table level lock)InnoDB層 行鎖消耗的時間。1、MySQL層utime_after_lock的記錄方式不管是 MDL LOCK等待消耗的時間還是 MyISAM表鎖消耗的時間都是在MySQL層記錄的,實際上它只是記錄在函數mysql_lock_tables的末尾會調用的THD::set_time_after_lock進行的記錄時間而已如下:void set_time_after_lock()
  • MySQL mysqldump 數據導出詳解
    是導出數據過程中使用非常頻繁的一個工具;它自帶的功能參數非常多,文章中會列舉出一些常用的操作,在文章末尾會將所有的參數詳細說明列出來。12--lock-tables, -l開始導出前,鎖定所有表。用READ LOCAL鎖定表以允許MyISAM表並行插入。對於支持事務的表例如InnoDB和BDB,--single-transaction是一個更好的選擇,因為它根本不需要鎖定表。請注意當導出多個資料庫時,--lock-tables分別為每個資料庫鎖定表。
  • 讀MySQL源碼再看 insert 加鎖流程,一個字:牛
    他的問題是這樣的:加了插入意向鎖後,插入數據之前,此時執行了 select...lock in share mode 語句(沒有取到待插入的值),然後插入了數據,下一次再執行 select...lock in share mode(不會跟插入意向鎖衝突),發現多了一條數據,於是又產生了幻讀。會出現這種情況嗎?
  • 尷尬的bug:一條查詢語句讓MySQL崩潰
    這是學習筆記的第 2028 篇文章  前幾天睡覺前接到前同事的一個信息,說有個奇怪的SQL問題,想讓我幫忙看看,給點建議,我以為是一種非常複雜的
  • MySQL 中的 INSERT 是怎麼加鎖的?
    來源:https://www.aneasystone.com/archives/2018/06/insert-locks-via-mysql-source-code.html看到熱心網友在評論中提出的一個問題,我還是徹底被問蒙了。
  • MySQL RR隔離級別死鎖分析一例
    在二級唯一索引c1上會做一個刪除和插入操作,也就是會將原來的「1,1」記錄標記為del flag,同時插入「2,1」這條記錄,這會引起一個鎖的繼承操作(lock_rec_inherit_to_gap_if_gap_lock調用會出現GAP LOCK)。
  • 我的投機取巧竟然忘了mysql還有一個最大值的限制
    而我不想在循環list了,我想一條sql搞定,因為mysql不是可以insert into table values(?,?),(?,?),(?,?)這樣寫嗎。我在mybatis中使用foreach就可以實現了。
  • 深入理解MySQL 5.7 GTID系列(六):MySQL啟動初始化GTID模塊
    (global_sid_map= new Sid_map(global_sid_lock)) || //new一個內存Sid_map內存空間出來     !(gtid_state= new Gtid_state(global_sid_lock, global_sid_map))||//new一個內存Gtid_state內存空間出來     !
  • MySQL InnoDB 引擎中的 7 種鎖類型,你都知道嗎?
    前言大概幾個月之前項目中用到事務,需要保證數據的強一致性,期間也用到了mysql的鎖,但當時對mysql的鎖機制只是管中窺豹,所以本文打算總結一下mysql的鎖機制。本文主要論述關於mysql鎖機制,mysql版本為5.7,引擎為innodb,由於實際中關於innodb鎖相關的知識及加鎖方式很多,所以沒有那麼多精力羅列所有場景下的加鎖過程並加以分析,僅根據現在了解的知識,結合官方文檔,說說自己的理解,如果發現有不對的地方,歡迎指正。概述總的來說,InnoDB共有七種類型的鎖:mysql鎖詳解1.
  • 認識mysql的鎖機制
    二、mysql鎖的分類Ⅰ、按粒度劃分1、表鎖表級鎖是mysql鎖中粒度最大的一種鎖,表示當前的操作對整張表加鎖。資源開銷比行鎖少,但是發生鎖衝突的概率很大。被大部分的mysql引擎支持,MyISAM和InnoDB都支持表級鎖。
  • MySQL - mysqldump常用命令 - linux運維菜
    ,不備份數據mysqldump -uroot -ppassword -A -d > database.sql3、只備份資料庫,不備份表結構mysqldump -uroot -ppassword -A -t > data.sql