一次MySQL(INNODB存儲引擎) 死鎖捉蟲記


前言

  任何系統不管在什么階段都需要關注生產環境錯誤日志,最近幾個月內,發現偶爾會出現數據庫死鎖情況。以前碰到的數據庫類錯誤大部分是SQL語法造成的錯誤,來到新東家之后才第一次碰到死鎖情況,以前是搞游戲開發,現在是搞電商類開發,可能是不同的項目不同的業務的原因吧,查閱了各種資料后發現,是我想錯了:(。一般業務瓶頸在數據庫層,對於數據庫層的問題需要重點關注,以為死鎖這種情況是很嚴重的問題,這個要分情況,偶爾死鎖對業務不會有太大的影響,我又想錯了:(。

 

蟲子發現
  第一次發現死鎖很驚訝,這個是什么鬼?不知道是什么原因?不知道怎么解決?不知道會不會影響業務?沒有搞清楚這個問題,生怕是業務的定時炸彈,每天心里不踏實。蟲子發現如下:

 

死鎖
  對數據庫記錄操作之前,當前線程需要先請求獲得相關鎖,獲得鎖之后才會執行SQL語句。鎖根據粒度分為表鎖和行鎖(不是所有存儲引擎都支持行鎖),鎖根據類型分為排他鎖和共享鎖(不同的操作需要獲得的鎖類型不同,不同的鎖類型行為也不相同)。資源越少,出現死鎖的概率會更小,比如只支持表鎖的存儲引擎會比支持行鎖的存儲引擎出現的概率更小。
  並發事務出現時,當出現多個事務間彼此等待對方資源釋放,事務因沒有處理完,已經獲得鎖的資源不會釋放,大家彼此這樣等待着僵持着,這樣會一直下去,死鎖就這樣產生了。
  死鎖現象關系型數據庫無法避免,不是MySQL 數據庫獨有。MySQL 數據庫會自動檢查死鎖情況,當發現時,會回滾更簡單的事務並返回給線程一個錯誤。怎么判斷哪個事務更簡單呢,根據事務影響的紀錄行數判斷,紀錄行數越小被認為更簡單。

 

診斷分析
  當出現死鎖時,為了解決這個問題,需要診斷分析當時出現死鎖的上下文信息以及相關的執行語句,這樣才能知道怎么避免。MySQL 數據庫只保存最近一次的死鎖事務,如果同時有超過2個事務出現死鎖,至多只保存2個事務信息。執行MySQL 客戶端命令:SHOW ENGINE INNODB STATUS獲得最近一次事務死鎖相關信息。如果是MySQL 5.6之后的版本,可以打開全局變量innodb_print_all_deadlocks=ON,這樣死鎖相關信息會保存到MySQL 錯誤日志中。如果是不支持這個變量的版本,可以采用定時執行客戶端命令采集死鎖信息,然后保存到日志文件中,每個事務都有唯一編號,可以根據這個去重。當死鎖頻繁出現時,需要引起注意;當偶爾出現時,可以不用關注。死鎖信息格式如下,不同MySQL 版本內容會有點差異,相關說明可以查看參考資料一。

 

預防措施
  知道死鎖為何物,以及通過分析診斷日志信息,就可以對症下葯了,但是有一些通用的基本原則可以遵守:
  1 盡可能保持事務簡單以及快速執行;
  2 盡可能保持事務影響行數少以及涉及的相關表少;
  3 避免使用外鍵約束,其實大部分應用允許數據冗余的;
  4 影響行數大的事務盡量使用相同的排序過濾;
  5 數據庫並發不高的業務,可以通過某種方式順序執行語句,一次只執行一個,通過查資料知道一種實現方式:創建一個表,這個表始終只有一條紀錄,各個事務通過爭奪這個鎖來實現線性執行,感覺這個應該沒啥用:(;
  6 有些場景死鎖會檢查不到,設置鎖的過期時間就很重要了,MySQL可以通過設置選項innodb_lock_wait_timeout;

 

危害程度
  鎖資源得不到及時釋放,會影響數據庫並發處理,如果經常出現死鎖,需要及時采取措施處理,如果只是偶爾出現,業務邏輯捕捉到死鎖錯誤可以采取重試執行事務,對業務不會有什么影響,總之具體問題需要具體分析:)

 

后記
  一開始遇到這個問題有點緊張,以為是很嚴重的問題,無從下手,不了解相關的背景知識嘛,看來人丑還是要多讀書啊(:(:

 

參考資料
【1】How to deal with MySQL deadlocks
https://www.percona.com/blog/2014/10/28/how-to-deal-with-mysql-deadlocks/
【2】deadlock
http://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_deadlock
【3】Deadlock Detection and Rollback
http://dev.mysql.com/doc/refman/5.7/en/innodb-deadlock-detection.html
【4】 How to Cope with Deadlocks
http://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM