這篇文章主要講解了“MySQL死鎖怎么檢測和避免”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“MySQL死鎖怎么檢測和避免”吧!
創(chuàng)新互聯(lián)建站擁有10余年的建站服務(wù)經(jīng)驗,在此期間,我們發(fā)現(xiàn)較多的客戶在挑選建站服務(wù)商前都非常的猶豫。主要問題集中:在無法預知自己的網(wǎng)站呈現(xiàn)的效果是什么樣的?也無法判斷選擇的服務(wù)商設(shè)計出來的網(wǎng)頁效果自己是否會滿意?創(chuàng)新互聯(lián)建站業(yè)務(wù)涵蓋了互聯(lián)網(wǎng)平臺網(wǎng)站建設(shè)、移動平臺網(wǎng)站制作、網(wǎng)絡(luò)推廣、定制開發(fā)等服務(wù)。創(chuàng)新互聯(lián)建站網(wǎng)站開發(fā)公司本著不拘一格的網(wǎng)站視覺設(shè)計和網(wǎng)站開發(fā)技術(shù)相結(jié)合,為企業(yè)做網(wǎng)站提供成熟的網(wǎng)站設(shè)計方案。
在我們使用鎖的時候,有一個問題是需要注意和避免的,我們知道,排它鎖有互斥的特性。一個事務(wù)或者說一個線程持有鎖的時候,會阻止其他的線程獲取鎖,這個時候會造成阻塞等待,如果循環(huán)等待,會有可能造成死鎖。
這個問題我們需要從幾個方面來分析,一個是鎖為什么不釋放,第二個是被阻塞了怎么辦,第三個死鎖是怎么發(fā)生的,怎么避免。
回顧:鎖什么時候釋放?
事務(wù)結(jié)束(commit,rollback)﹔
客戶端連接斷開。
如果一個事務(wù)一直未釋放鎖,其他事務(wù)會被阻塞多久?會不會永遠等待下去?
如果是,在并發(fā)訪問比較高的情況下,如果大量事務(wù)因無法立即獲得所需的鎖而掛起,會占用大量計算機資源,造成嚴重性能問題,甚至拖跨數(shù)據(jù)庫。
線上怕不怕這個錯?
[Err] 1205 - Lock wait timeout exceeded; try restarting transaction
MySQL有一個參數(shù)來控制獲取鎖的等待時間,默認是50秒。
show VARIABLES like "innodb_lock_wait_timeout";
對于死鎖,是無論等多久都不能獲取到鎖的,這種情況,也需要等待50秒鐘嗎?那不是白白浪費了50秒鐘的時間嗎?
演示一下,開兩個會話:
方便對時間線的提現(xiàn),這里用圖片,有興趣的可以跟著模仿一下
栗子一:
栗子二:
在第一個事務(wù)中,檢測到了死鎖,馬上退出了,第二個事務(wù)獲得了鎖,不需要等待50秒:
[Err] 1213 - Deadlock found when trying to get lock; try restarting transaction
為什么可以直接檢測到呢?是因為死鎖的發(fā)生需要滿足一定的條件,對于我們程序員來說,有明確的條件,意味著能判定,所以在發(fā)生死鎖時,InnoDB一般都能通過算法(wait-for graph)自動檢測到。
那么死鎖需要滿足什么條件?死鎖的產(chǎn)生條件,因為鎖本身是互斥的:
(1)同一時刻只能有一個事務(wù)持有這把鎖;
(2)其他的事務(wù)需要在這個事務(wù)釋放鎖之后才能獲取鎖,而不可以強行剝奪;
(3)當多個事務(wù)形成等待環(huán)路的時候,即發(fā)生死鎖。
理發(fā)店有兩個總監(jiān)。一個負責剪頭的Tony老師,一個負責洗頭的Kelvin老師。Tony老師不能同時給兩個人剪頭,這個就叫互斥
。
Tony在給別人在剪頭的時候,你不能讓他停下來幫你剪頭,這個叫不能強行剝奪
。
如果Tony的客戶對Kelvin說:你不幫我洗頭我怎么剪頭? Kelvin 的客戶對Tony說:你不幫我剪頭我怎么洗頭?這個就叫形成等待環(huán)路
。
實際上,發(fā)生死鎖的情況非常多,但是都滿足以上3個條件。
這個也是表鎖是不會發(fā)生死鎖的原因,因為表鎖的資源都是一次性獲取的。
如果鎖一直沒有釋放,就有可能造成大量阻塞或者發(fā)生死鎖,造成系統(tǒng)吞吐量下降,這時候就要查看是哪些事務(wù)持有了鎖。
首先,SHow STATUS命令中,包括了一些行鎖的信息:
show status like 'innodb_row_lock_%';
lnnodb_row_lock_current_waits:當前正在等待鎖定的數(shù)量;
lnnodb_row_lock_time :從系統(tǒng)啟動到現(xiàn)在鎖定的總時間長度,單位ms;
Innodb_row_lock_time_avg :每次等待所花平均時間;
Innodb_row_lock_time_max:從系統(tǒng)啟動到現(xiàn)在等待最長的一次所花的時間;
lnnodb_row_lock_waits :從系統(tǒng)啟動到現(xiàn)在總共等待的次數(shù)。
SHOW命令是一個概要信息。InnoDB還提供了三張表來分析事務(wù)與鎖的情況:
select * from information_schema.INNODB_TRX; --當前運行的所有事務(wù)﹐還有具體的語句
select* from information_schema.INNODB_LOCKS; --當前出現(xiàn)的鎖
select * from information_schema.INNODB_LOCK_WAITS; --鎖等待的對應(yīng)關(guān)系
更加詳細的鎖信息,開啟標準監(jiān)控和鎖監(jiān)控:
額外的監(jiān)控肯定會消耗額外的性能
set GLOBAL innodb_status_output=ON; set GLOBAL innodb_status_output_locks=ON;
通過分析鎖日志,找出持有鎖的事務(wù)之后呢?
如果一個事務(wù)長時間持有鎖不釋放,可以kill事務(wù)對應(yīng)的線程ID,也就是INNODB_TRX表中的trx_mysql_thread_id,例如執(zhí)行kill 4,kill 7, kill 8。
當然,死鎖的問題不能每次都靠kill線程來解決,這是治標不治本的行為。我們應(yīng)該盡量在應(yīng)用端,也就是在編碼的過程中避免。
有哪些可以避免死鎖的方法呢?
1、在程序中,操作多張表時,盡量以相同的順序來訪問(避免形成等待環(huán)路)
2、批量操作單張表數(shù)據(jù)的時候,先對數(shù)據(jù)進行排序(避免形成等待環(huán)路);
3、申請足夠級別的鎖,如果要操作數(shù)據(jù),就申請排它鎖;
4、盡量使用索引訪問數(shù)據(jù),避免沒有where條件的操作,避免鎖表;
5、如果可以,大事務(wù)化成小事務(wù);
6、使用等值查詢而不是范圍查詢查詢數(shù)據(jù),命中記錄,避免間隙鎖對并發(fā)的影響。
感謝各位的閱讀,以上就是“MySQL死鎖怎么檢測和避免”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對MySQL死鎖怎么檢測和避免這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
標題名稱:MySQL死鎖怎么檢測和避免
網(wǎng)頁URL:http://jinyejixie.com/article32/iehesc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗、營銷型網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計公司、云服務(wù)器、企業(yè)建站、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)