MySQL死鎖怎么檢測(cè)和避免

這篇文章主要講解了“MySQL死鎖怎么檢測(cè)和避免”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“MySQL死鎖怎么檢測(cè)和避免”吧!

創(chuàng)新互聯(lián)建站擁有10余年的建站服務(wù)經(jīng)驗(yàn),在此期間,我們發(fā)現(xiàn)較多的客戶(hù)在挑選建站服務(wù)商前都非常的猶豫。主要問(wèn)題集中:在無(wú)法預(yù)知自己的網(wǎng)站呈現(xiàn)的效果是什么樣的?也無(wú)法判斷選擇的服務(wù)商設(shè)計(jì)出來(lái)的網(wǎng)頁(yè)效果自己是否會(huì)滿(mǎn)意?創(chuàng)新互聯(lián)建站業(yè)務(wù)涵蓋了互聯(lián)網(wǎng)平臺(tái)網(wǎng)站建設(shè)、移動(dòng)平臺(tái)網(wǎng)站制作、網(wǎng)絡(luò)推廣、定制開(kāi)發(fā)等服務(wù)。創(chuàng)新互聯(lián)建站網(wǎng)站開(kāi)發(fā)公司本著不拘一格的網(wǎng)站視覺(jué)設(shè)計(jì)和網(wǎng)站開(kāi)發(fā)技術(shù)相結(jié)合,為企業(yè)做網(wǎng)站提供成熟的網(wǎng)站設(shè)計(jì)方案。

在我們使用鎖的時(shí)候,有一個(gè)問(wèn)題是需要注意和避免的,我們知道,排它鎖有互斥的特性。一個(gè)事務(wù)或者說(shuō)一個(gè)線(xiàn)程持有鎖的時(shí)候,會(huì)阻止其他的線(xiàn)程獲取鎖,這個(gè)時(shí)候會(huì)造成阻塞等待,如果循環(huán)等待,會(huì)有可能造成死鎖。

這個(gè)問(wèn)題我們需要從幾個(gè)方面來(lái)分析,一個(gè)是鎖為什么不釋放,第二個(gè)是被阻塞了怎么辦,第三個(gè)死鎖是怎么發(fā)生的,怎么避免。

鎖的釋放與阻塞

回顧:鎖什么時(shí)候釋放?
事務(wù)結(jié)束(commit,rollback)﹔
客戶(hù)端連接斷開(kāi)。

如果一個(gè)事務(wù)一直未釋放鎖,其他事務(wù)會(huì)被阻塞多久?會(huì)不會(huì)永遠(yuǎn)等待下去?
如果是,在并發(fā)訪(fǎng)問(wèn)比較高的情況下,如果大量事務(wù)因無(wú)法立即獲得所需的鎖而掛起,會(huì)占用大量計(jì)算機(jī)資源,造成嚴(yán)重性能問(wèn)題,甚至拖跨數(shù)據(jù)庫(kù)。

線(xiàn)上怕不怕這個(gè)錯(cuò)?

[Err] 1205 - Lock wait timeout exceeded; try restarting transaction

MySQL有一個(gè)參數(shù)來(lái)控制獲取鎖的等待時(shí)間,默認(rèn)是50秒。

show VARIABLES like "innodb_lock_wait_timeout";

對(duì)于死鎖,是無(wú)論等多久都不能獲取到鎖的,這種情況,也需要等待50秒鐘嗎?那不是白白浪費(fèi)了50秒鐘的時(shí)間嗎?

死鎖的發(fā)生和檢測(cè)

演示一下,開(kāi)兩個(gè)會(huì)話(huà):

方便對(duì)時(shí)間線(xiàn)的提現(xiàn),這里用圖片,有興趣的可以跟著模仿一下

栗子一:

MySQL死鎖怎么檢測(cè)和避免

栗子二:

MySQL死鎖怎么檢測(cè)和避免

在第一個(gè)事務(wù)中,檢測(cè)到了死鎖,馬上退出了,第二個(gè)事務(wù)獲得了鎖,不需要等待50秒:

[Err] 1213 - Deadlock found when trying to get lock; try restarting transaction

為什么可以直接檢測(cè)到呢?是因?yàn)樗梨i的發(fā)生需要滿(mǎn)足一定的條件,對(duì)于我們程序員來(lái)說(shuō),有明確的條件,意味著能判定,所以在發(fā)生死鎖時(shí),InnoDB一般都能通過(guò)算法(wait-for graph)自動(dòng)檢測(cè)到。

那么死鎖需要滿(mǎn)足什么條件?死鎖的產(chǎn)生條件,因?yàn)殒i本身是互斥的:

  • (1)同一時(shí)刻只能有一個(gè)事務(wù)持有這把鎖;

  • (2)其他的事務(wù)需要在這個(gè)事務(wù)釋放鎖之后才能獲取鎖,而不可以強(qiáng)行剝奪;

  • (3)當(dāng)多個(gè)事務(wù)形成等待環(huán)路的時(shí)候,即發(fā)生死鎖。

理發(fā)店有兩個(gè)總監(jiān)。一個(gè)負(fù)責(zé)剪頭的Tony老師,一個(gè)負(fù)責(zé)洗頭的Kelvin老師。Tony老師不能同時(shí)給兩個(gè)人剪頭,這個(gè)就叫互斥

Tony在給別人在剪頭的時(shí)候,你不能讓他停下來(lái)幫你剪頭,這個(gè)叫不能強(qiáng)行剝奪。
如果Tony的客戶(hù)對(duì)Kelvin說(shuō):你不幫我洗頭我怎么剪頭? Kelvin 的客戶(hù)對(duì)Tony說(shuō):你不幫我剪頭我怎么洗頭?這個(gè)就叫形成等待環(huán)路。
實(shí)際上,發(fā)生死鎖的情況非常多,但是都滿(mǎn)足以上3個(gè)條件。
這個(gè)也是表鎖是不會(huì)發(fā)生死鎖的原因,因?yàn)楸礞i的資源都是一次性獲取的。

如果鎖一直沒(méi)有釋放,就有可能造成大量阻塞或者發(fā)生死鎖,造成系統(tǒng)吞吐量下降,這時(shí)候就要查看是哪些事務(wù)持有了鎖。

查看鎖信息(日志)

首先,SHow STATUS命令中,包括了一些行鎖的信息:

show status like 'innodb_row_lock_%';

MySQL死鎖怎么檢測(cè)和避免

lnnodb_row_lock_current_waits:當(dāng)前正在等待鎖定的數(shù)量;
lnnodb_row_lock_time :從系統(tǒng)啟動(dòng)到現(xiàn)在鎖定的總時(shí)間長(zhǎng)度,單位ms;
Innodb_row_lock_time_avg :每次等待所花平均時(shí)間;
Innodb_row_lock_time_max:從系統(tǒng)啟動(dòng)到現(xiàn)在等待最長(zhǎng)的一次所花的時(shí)間;
lnnodb_row_lock_waits :從系統(tǒng)啟動(dòng)到現(xiàn)在總共等待的次數(shù)。

SHOW命令是一個(gè)概要信息。InnoDB還提供了三張表來(lái)分析事務(wù)與鎖的情況:

select * from information_schema.INNODB_TRX; --當(dāng)前運(yùn)行的所有事務(wù)﹐還有具體的語(yǔ)句

MySQL死鎖怎么檢測(cè)和避免

select* from information_schema.INNODB_LOCKS; --當(dāng)前出現(xiàn)的鎖

MySQL死鎖怎么檢測(cè)和避免

select * from information_schema.INNODB_LOCK_WAITS; --鎖等待的對(duì)應(yīng)關(guān)系

MySQL死鎖怎么檢測(cè)和避免

更加詳細(xì)的鎖信息,開(kāi)啟標(biāo)準(zhǔn)監(jiān)控和鎖監(jiān)控:

額外的監(jiān)控肯定會(huì)消耗額外的性能

set GLOBAL innodb_status_output=ON;
set GLOBAL innodb_status_output_locks=ON;

通過(guò)分析鎖日志,找出持有鎖的事務(wù)之后呢?
如果一個(gè)事務(wù)長(zhǎng)時(shí)間持有鎖不釋放,可以kill事務(wù)對(duì)應(yīng)的線(xiàn)程ID,也就是INNODB_TRX表中的trx_mysql_thread_id,例如執(zhí)行kill 4,kill 7, kill 8。
當(dāng)然,死鎖的問(wèn)題不能每次都靠kill線(xiàn)程來(lái)解決,這是治標(biāo)不治本的行為。我們應(yīng)該盡量在應(yīng)用端,也就是在編碼的過(guò)程中避免。
有哪些可以避免死鎖的方法呢?

死鎖的避免

  • 1、在程序中,操作多張表時(shí),盡量以相同的順序來(lái)訪(fǎng)問(wèn)(避免形成等待環(huán)路)

  • 2、批量操作單張表數(shù)據(jù)的時(shí)候,先對(duì)數(shù)據(jù)進(jìn)行排序(避免形成等待環(huán)路);

  • 3、申請(qǐng)足夠級(jí)別的鎖,如果要操作數(shù)據(jù),就申請(qǐng)排它鎖;

  • 4、盡量使用索引訪(fǎng)問(wèn)數(shù)據(jù),避免沒(méi)有where條件的操作,避免鎖表;

  • 5、如果可以,大事務(wù)化成小事務(wù);

  • 6、使用等值查詢(xún)而不是范圍查詢(xún)查詢(xún)數(shù)據(jù),命中記錄,避免間隙鎖對(duì)并發(fā)的影響。

感謝各位的閱讀,以上就是“MySQL死鎖怎么檢測(cè)和避免”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)MySQL死鎖怎么檢測(cè)和避免這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

標(biāo)題名稱(chēng):MySQL死鎖怎么檢測(cè)和避免
網(wǎng)頁(yè)URL:http://muchs.cn/article32/iehesc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶(hù)體驗(yàn)、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司、云服務(wù)器、企業(yè)建站、外貿(mào)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站