mysql 死鎖和死鎖檢測(cè)的實(shí)現(xiàn)
1、死鎖的定義
當(dāng)mysql請(qǐng)求發(fā)生并發(fā)時(shí),不同線程執(zhí)行的事務(wù)操作需要獲取相同資源的鎖,涉及的線程都在等待別的線程釋放鎖,幾個(gè)線程都進(jìn)入無限等待的狀態(tài)時(shí),就出現(xiàn)死鎖了。
2、鎖等待的最大時(shí)長(zhǎng)
當(dāng)出現(xiàn)死鎖時(shí),事務(wù)會(huì)一直等待,直到時(shí)間達(dá)到innodb_lock_wait_timeout設(shè)置的值,默認(rèn)值是50秒。
3、死鎖檢測(cè)
可以設(shè)置innodb_deadlock_detect=on 來開啟死鎖檢測(cè)。死鎖檢測(cè)在發(fā)生死鎖的時(shí)候,能夠快速發(fā)現(xiàn)并進(jìn)行處理,回滾并重新啟動(dòng)。但是死鎖檢測(cè)會(huì)比較好資源。當(dāng)每個(gè)新來的被堵住的線程,都要判斷會(huì)不會(huì)由于自己的加入導(dǎo)致了死鎖,這是一個(gè)時(shí)間復(fù)雜度是 O(n) 的操作。假設(shè)有 1000 個(gè)并發(fā)線程要同時(shí)更新同一行,那么死鎖檢測(cè)操作可能就是 100 萬的量級(jí)。雖然最終檢測(cè)的結(jié)果可能沒有死鎖,但是這期間要消耗大量的 CPU 資源。
4、innodb死鎖的監(jiān)控和查看
innodb引擎,查看死鎖信息,可以通過以下兩種方式:
查看SHOW ENGINE INNODB STATUS
命令的輸出:
SHOW ENGINE INNODB STATUS;
這將顯示InnoDB的當(dāng)前狀態(tài),包括最近的死鎖信息(如果發(fā)生過的話)。死鎖信息包括受影響的事務(wù)、相關(guān)的SQL語句、鎖等待信息等。
借助錯(cuò)誤日志:
如果啟用了InnoDB監(jiān)控(innodb_print_all_deadlocks
),所有的死鎖信息都會(huì)被記錄到MySQL的錯(cuò)誤日志文件中。要啟用該功能,你可以在MySQL配置文件中設(shè)置:
[mysqld] innodb_print_all_deadlocks=1
然后重啟MySQL服務(wù)。注意,頻繁的死鎖可能導(dǎo)致日志文件迅速膨脹,因此在生產(chǎn)環(huán)境中應(yīng)謹(jǐn)慎使用。
5、防止死鎖的一些策略
雖然不能完全避免死鎖,但可以采取一些措施來最小化其發(fā)生的頻率:
保持一致的鎖定順序:確保所有的事務(wù)按照相同的順序請(qǐng)求鎖。
使用鎖超時(shí):通過innodb_lock_wait_timeout
設(shè)置合理的鎖等待超時(shí)時(shí)間。
盡量減少事務(wù)大小:大事務(wù)更容易導(dǎo)致死鎖。
快速提交事務(wù):進(jìn)行一系列相關(guān)更改后,應(yīng)立即提交事務(wù)以減少?zèng)_突風(fēng)險(xiǎn)。特別是要避免在mysql會(huì)話中長(zhǎng)時(shí)間保持未提交的事務(wù)。
使用較低隔離級(jí)別的鎖定讀取:若使用了 SELECT ... FOR UPDATE
或 SELECT ... FOR SHARE
,可以考慮采用 READ COMMITTED
這樣更低的隔離級(jí)別。
盡量使用索引:通過確保SQL語句使用到索引以減少鎖的范圍。
減少鎖的使用:如果允許SELECT返回非最新數(shù)據(jù),則無需在其上添加 FOR UPDATE
或 FOR SHARE
子句。READ COMMITTED
隔離級(jí)別在此場(chǎng)景下非常有效。
使用表級(jí)鎖來串行化事務(wù):如所有其他方法都無效,可以使用表級(jí)鎖。正確地使用 LOCK TABLES
應(yīng)先設(shè)置 SET autocommit = 0
開啟事務(wù),然后再執(zhí)行 LOCK TABLES
,并在顯式提交事務(wù)之前不要解鎖。例如:
SET autocommit=0; LOCK TABLES t1 WRITE, t2 READ, ...; ... 在這里對(duì)表 t1 和 t2 進(jìn)行操作 ... COMMIT; UNLOCK TABLES;
表級(jí)鎖可以阻止表的并發(fā)更新,避免死鎖,但代價(jià)是減少系統(tǒng)忙碌時(shí)的響應(yīng)能力。
- 分析和優(yōu)化查詢:分析查詢性能,優(yōu)化長(zhǎng)時(shí)間運(yùn)行的查詢以減少它們持有鎖的時(shí)間。
- 創(chuàng)建“信號(hào)量”表來序列化事務(wù):在事務(wù)開始前,它首先嘗試更新信號(hào)量表中的唯一記錄。如果某個(gè)事務(wù)已經(jīng)鎖定了這條記錄以執(zhí)行更新,其他事務(wù)必須等待直到該記錄被解鎖才能繼續(xù),從而實(shí)現(xiàn)強(qiáng)制的順序執(zhí)行。這樣做確保了每次只有一個(gè)事務(wù)可以執(zhí)行更新操作,防止了多個(gè)事務(wù)同時(shí)運(yùn)行,可能導(dǎo)致死鎖的情況發(fā)生。
適當(dāng)設(shè)計(jì)和調(diào)優(yōu)數(shù)據(jù)庫操作,特別是確保正確使用事務(wù),可以顯著減少死鎖的發(fā)生。
到此這篇關(guān)于mysql 死鎖和死鎖檢測(cè)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)mysql 死鎖和死鎖檢測(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL中二進(jìn)制與重做日志文件的基本概念學(xué)習(xí)教程
這篇文章主要介紹了MySQL中二進(jìn)制日志文件與重做日志文件的基本概念學(xué)習(xí)教程,講到了一些重做日志與二進(jìn)制日志的區(qū)別,需要的朋友可以參考下2015-11-11用MyEclipse配置DataBase Explorer(圖示)
本文介紹了,用MyEclipse配置DataBase Explorer的圖片示例。需要的朋友參考下2013-04-04MySQL 5.7臨時(shí)表空間如何玩才能不掉坑里詳解
這篇文章主要給大家介紹了關(guān)于MySQL 5.7臨時(shí)表空間如何玩才能不掉坑里的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用mysql具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起看看吧2018-09-09mysql獲取指定時(shí)間段中所有日期或月份的語句(不設(shè)存儲(chǔ)過程,不加表)
最近需要用mysql獲取一個(gè)時(shí)間段中的所有月份,網(wǎng)上查都是要設(shè)置存儲(chǔ)過程或者加一個(gè)日期表的,不滿足我的需求,翻墻找資料加上自己試驗(yàn),如下代碼分享給大家2021-06-06MySQL安裝三種方法總結(jié)(yum安裝、編譯安裝、二進(jìn)制安裝)
MySQL安裝網(wǎng)上的教程有很多,基本上大同小異,但是安裝軟件有時(shí)就可能因?yàn)橐粋€(gè)細(xì)節(jié)安裝失敗,這篇文章主要介紹了MySQL安裝三種方法的相關(guān)資料,三種方法分別是yum安裝、編譯安裝以及二進(jìn)制安裝,需要的朋友可以參考下2023-12-12MySQL BinLog如何恢復(fù)誤更新刪除數(shù)據(jù)
這篇文章主要介紹了MySQL BinLog如何恢復(fù)誤更新刪除數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06