MySQL阻塞與死鎖的解決
阻塞
因為不同鎖之間的兼容性關(guān)系,在有些時刻一個事務(wù)中的鎖需要等待另一個事務(wù)中的鎖釋放它所占用的資源,這就是阻塞。
# 查看等待時間 show variables like 'innodb_lock_wait_timeout'; SET@@innodb_lock_wait_timeout=60; # 是否在等待超時時對進行中的事務(wù)進行回滾操作 show variables like 'innodb_rollback_on_timeout'; #設(shè)置等待時間 默認50秒 SET@@innodb_lock_wait_timeout=60; #設(shè)置是否在等待超時時對進行中的事務(wù)進行回滾操作 默認是OFF 代表不回滾 SET@@innodb_rollback_on_timeout=on;
查詢:
設(shè)置值:
注意:參數(shù) innodb_lock_wait_timeout
參數(shù)是動態(tài)的,在mysql運行時可進行調(diào)整, innodb_rollback_on_timeout
參數(shù)是靜態(tài)的,不可在運行時進行修改,否則會報錯。
需要特別注意:在默認情況下InnoDB存儲引擎不會回滾超時引發(fā)的錯誤異常。(其實InnoDB存儲引擎在大部分情況下都不會對異常進行回滾。)
異常實例演示:
左邊為會話A,右邊為會話B。初始狀態(tài)數(shù)據(jù)庫表film中有3條數(shù)據(jù),ID,分別為3,5,6;
首先會話A 開啟了事務(wù)A,并且在Next-Key Lock算法下鎖定了小與5包含5的記錄。事務(wù)B正常插入記錄ID:7,當插入ID:4 時就進人阻塞狀態(tài)了
當事務(wù)B達到事務(wù)超時間時間時,報錯 ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
.
這時事務(wù)B在此查詢會發(fā)現(xiàn),**ID:7 這條記錄依然存在,這是因為事務(wù)B雖然拋出了異常,但是既沒有進行commit 操作也沒有進行 rollback操作。**這是非常危險的,因為此時數(shù)據(jù)庫一致性特性被打破了。因此此時用戶必須判斷是否需要COMMIT還是ROLLBACK,之后再進行下一步的操作。
一般情況這時事務(wù)B需要進行 rollback操作,具體情況具體分析。
死鎖
死鎖是指兩個或兩個以上的事務(wù)在執(zhí)行過程中,因爭奪鎖資源而造成的一種互相等待的現(xiàn)象。
當發(fā)生死鎖的時候,若無外力作用事務(wù)都將無法進行下去。
死鎖產(chǎn)生的條件:
- 互斥條件
臨界資源是獨占資源,進程應(yīng)互斥且排他的使用這些資源。 - 占有和等待條件
進程在請求資源得不到滿足而等待時,不釋放已占有資源。 - 不剝奪條件
又稱不可搶占,已獲資源只能由進程自愿釋放,不允許被其他進程剝奪。 - 循環(huán)等待條件
又稱環(huán)路條件,存在循環(huán)等待鏈,其中,每個進程都在等待鏈中等待下一個進程所持有的資源,造成這組進程處于永遠等待狀態(tài)。
如何解決死鎖問題:
1.超時機制:當兩個事務(wù)互相等待時,如果等待時間超過設(shè)置的某一閾值時,其中一個事務(wù)進行回滾,另一個等待的事務(wù)就能繼續(xù)進行。在InnoDB存儲引擎中, innodb_lock_wait_timeout
設(shè)置超時的時間。
我們知道,一條記錄是有很多undo log的或者undo 版本鏈有很多版本的,如果一個事務(wù)操作更新了很多行,這時候如果要進行回滾所占用的時間可能就會很多。
2.使用wai t-for graph (等待圖)進行死鎖檢測,數(shù)據(jù)庫需要保存鎖的信息鏈表和事務(wù)等待鏈表。我們通過鎖的信息鏈表和事務(wù)等待鏈表就可以構(gòu)造出一張圖,如果圖中存在回路那就說明出現(xiàn)了死鎖。
? 事務(wù)和鎖狀態(tài)圖
上圖中,transaction wait list 中有四個事務(wù),事務(wù)t2對row1加了x鎖,事務(wù)t1對row1加了s鎖,并且事務(wù)t1需要等待事務(wù)t2中的row1資源,因此wait-for graph圖中有一條邊沖節(jié)點t1指向t2。 row2記錄的情況同理。
? wait-for graph
觀察發(fā)現(xiàn),t1 和 t2 存在回路,因此存在死鎖。
閱讀到這里,我們需要意識到因為MySQL數(shù)據(jù)庫是一個并發(fā)的程序,所以才存在死鎖。因為如果程序是串行的,那么也就不會發(fā)生死鎖了。
死鎖示例:
有兩個事務(wù)A,B: 事務(wù)A當前讀查詢記錄ID:5 ,事務(wù)B當前讀查詢ID:6。
接著交換一下:
事務(wù)A當前讀查詢記錄ID:6 ,事務(wù)B當前讀查詢ID:5
會發(fā)現(xiàn)兩個事務(wù)中的事務(wù)B立馬就報錯: ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
通常來說InnoDB存儲引擎選擇回滾undo量最小的事務(wù)。
到此這篇關(guān)于MySQL阻塞與死鎖的解決的文章就介紹到這了,更多相關(guān)MySQL阻塞與死鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mysql插入數(shù)據(jù)方式(insert into 、replace into解析)
這篇文章主要介紹了Mysql插入數(shù)據(jù)方式(insert into 、replace into解析),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01MySQL數(shù)據(jù)庫基礎(chǔ)篇SQL窗口函數(shù)示例解析教程
這篇文章主要為大家介紹了MySQL數(shù)據(jù)庫基礎(chǔ)篇之窗口函數(shù)示例解析教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-10-10MySql,MVCC實現(xiàn)及其機制,快照讀在RC,RR下的區(qū)別說明
這篇文章主要介紹了MySql,MVCC實現(xiàn)及其機制,快照讀在RC,RR下的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04