MySQL之死鎖問題及其解決方案
前言
數(shù)據(jù)庫死鎖問題是我們老生常談的問題了,在我們實際開發(fā)過程中經(jīng)常會遇到,為了盡量避免出現(xiàn)死鎖,我們需要了解出現(xiàn)死鎖的場景。同時,如果線上出現(xiàn)了死鎖之后怎么去分析、排查和解決,下面我就這兩點介紹一下。
一、數(shù)據(jù)庫死鎖介紹
1、什么是數(shù)據(jù)庫死鎖?
數(shù)據(jù)庫的死鎖是指:不同的事務在獲取資源時相互等待,導致無法繼續(xù)執(zhí)行的一種情況。當發(fā)生死鎖時,數(shù)據(jù)庫系統(tǒng)會自動中斷其中一個事務,以解除死鎖。在數(shù)據(jù)庫中,事務可以分為讀事務和寫事務。讀事務只需要獲取讀鎖,而寫事務需要獲取寫鎖。當多個事務同時操作同一組數(shù)據(jù)時,可能會引發(fā)死鎖的出現(xiàn)。
2、MySQL 發(fā)生死鎖的場景
2-1、事務同時更新多個表
當一個事務同時更新多個表并且使用了不同的順序,可能會導致死鎖的發(fā)生。例如,事務 A 首先更新表 X,此時獲取到了 X 表的鎖,并在未釋放該鎖的情況下嘗試更新表 Y;而事務 B 首先更新表Y,此時獲取到了 Y 表的鎖,并在未釋放鎖的情況下嘗試更新表 X。這種情況下,兩個事務會相互等待對方的鎖釋放,從而形成死鎖。
2-2、事務嵌套
當一個事務內部開啟了另一個事務,并在內層事務中更新了某個表,而外層事務也需要更新該表的同一行記錄時,就有可能發(fā)生死鎖。因為外層事務需要等待內層事務釋放鎖,而內層事務需要等待外層事務釋放鎖。
2-3、索引順序不一致
當多個事務按照不同的順序訪問相同的數(shù)據(jù)行,并且使用了不同的索引時,可能會發(fā)生死鎖。例如,事務 A 按照索引 1 的順序訪問數(shù)據(jù)行,事務 B 按照索引 2 的順序訪問同一組數(shù)據(jù)行,這樣兩個事務之間就會產生死鎖。
2-4、不同事務同時更新相同的索引
當多個事務同時更新相同的索引時,可能會導致死鎖。這是因為事務在更新索引時會獲取對應的鎖,并在未釋放鎖的情況下嘗試更新其他數(shù)據(jù),從而形成死鎖。
二、解決死鎖問題
如果線上發(fā)生了死鎖,我們應該采取以下步驟進行處理:
1、 監(jiān)控死鎖
正常情況下我們都會建立死鎖監(jiān)控機制,以便及時掌握死鎖情況;同時設置相應的預警機制,以便在死鎖發(fā)生時能夠及時處理。
通過數(shù)據(jù)庫的監(jiān)控工具或命令可以查看是否存在死鎖情況,如果出現(xiàn)則了解死鎖的具體情況,包括死鎖的事務和死鎖的資源。
2、終止死鎖事務
根據(jù)監(jiān)控結果,找到造成死鎖的事務,并手動選擇其中一個事務終止??梢愿鶕?jù)事務的執(zhí)行時間、影響行數(shù)、優(yōu)先級等因素進行終止決策。可以通過 select * from information_schema.innodb_trx 語句查看死鎖情況。
在 innodb 中,有三張表可以幫助我們更好去分析死鎖信息:
- information_schema.innodb_trx:事務信息表。
- information_schema.innodb_locks:事務鎖的信息表。
- information_schema.innodb_lock_waits:鎖等待關系表。
系統(tǒng)自動解除死鎖:
正常情況下,當發(fā)生死鎖時,MySQL 系統(tǒng)會自動解除死鎖,至于解除哪個事務的鎖,需要虧了一個代價,在解除死鎖方面,會選擇回滾事務產生影響最小的一個進行回滾。
這里就要提一下兩個概念了,一個是事務的權重(trx_weight),另外一個是事務的調度權重(trx_schedule_weight):
- 事務的權重:與回滾事務的選擇有關。具體與事務 undo 版本鏈的長度有關,回滾的 undo 記錄越多,產生的影響就會越大,MySQL 就不會選擇這樣的事務,倘若事務權重一樣,會選擇事務等待隊列等待時間短的事務進行回滾。
- 事務的調度權重:與事務獲取資源的先后有關。MySQL8.0.20 之前在等待鎖的事務優(yōu)先級排序采取 FIFO 算法,之后采取 CATS 算法。該算法通過分配調度權限對等待的事務進行優(yōu)先級排序,該權重是根據(jù)事務阻塞的事務數(shù)量計算的。例如,兩個事務正在等待同一對象上的鎖,那么阻塞最多事務的事務將被分配更大的調度權重,如果權重相等,則優(yōu)先考慮等待時間最長的事務分配資源。
3、重試事務
終止死鎖事務后,需要重新執(zhí)行被終止的事務。這可能需要一些邏輯處理,例如對數(shù)據(jù)進行回滾或者重新執(zhí)行一些操作。
4、分析死鎖原因
通過數(shù)據(jù)庫的日志和監(jiān)控信息,分析死鎖的原因。下面是查看死鎖日志的命令語句:
show engine innodb status;
分析死鎖日志然后根據(jù)死鎖原因對數(shù)據(jù)庫的設計和代碼進行優(yōu)化,以盡量減少死鎖的發(fā)生。
同時也可以根據(jù)分析結果,針對性地進行數(shù)據(jù)庫結構調整、索引優(yōu)化、事務隔離級別調整等措施,以降低死鎖的概率。
5、避免死鎖建議
- 事務盡可能小,不要將復雜邏輯放進一個事務里。
- 涉及多行記錄時,約定不同事務以相同順序訪問。
- 業(yè)務中要及時提交或者回滾事務,可減少死鎖產生的概率。
- 表要有合適的索引。
- 可嘗試將隔離級別改為 ReadCommit 。
到此這篇關于MySQL之死鎖問題及其解決方案的文章就介紹到這了,更多相關MySQL 死鎖內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mysql安裝navicat之后,出現(xiàn)2059,Authentication plugin及本地鏈接虛擬機docker,
這篇文章主要介紹了mysql安裝navicat之后,出現(xiàn)2059,Authentication plugin及本地鏈接虛擬機docker,遠程鏈接服務器,需要的朋友可以參考下2020-06-06
Mysql中substring_index函數(shù)實現(xiàn)字符分割一行變多行
在MySQL中,字符串分割是一個常見的操作,本文主要介紹了Mysql中substring_index函數(shù)實現(xiàn)字符分割一行變多行,具有一定的參考價值,感興趣的可以了解一下2023-12-12
解決MySQL 5.7.9版本sql_mode=only_full_group_by問題
這篇文章主要介紹了解決MySQL 5.7.9版本sql_mode=only_full_group_by問題,需要的朋友可以參考下2017-05-05
windows 10 下mysql-8.0.17-winx64的安裝方法圖解
這篇文章主要介紹了windows 10 mysql-8.0.17-winx64的方法,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08
MySQL中union和join語句使用區(qū)別的辨析教程
這篇文章主要介紹了MySQL中union和join語句的用法區(qū)別,舉例說明了union和join在連接操作上的不同作用,需要的朋友可以參考下2015-12-12

