久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL死鎖怎么檢測和避免

167次閱讀
沒有評論

共計 2364 個字符,預(yù)計需要花費 6 分鐘才能閱讀完成。

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

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

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

鎖的釋放與阻塞

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

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

線上怕不怕這個錯?

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

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

show VARIABLES like  innodb_lock_wait_timeout

對于死鎖,是無論等多久都不能獲取到鎖的,這種情況,也需要等待 50 秒鐘嗎? 那不是白白浪費了 50 秒鐘的時間嗎?

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

演示一下,開兩個會話:

方便對時間線的提現(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)當(dāng)多個事務(wù)形成等待環(huán)路的時候,即發(fā)生死鎖。

理發(fā)店有兩個總監(jiān)。一個負(fù)責(zé)剪頭的 Tony 老師,一個負(fù)責(zé)洗頭的 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: 當(dāng)前正在等待鎖定的數(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; -- 當(dāng)前運行的所有事務(wù)﹐還有具體的語句

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

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

更加詳細(xì)的鎖信息,開啟標(biāo)準(zhǔ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。
當(dāng)然,死鎖的問題不能每次都靠 kill 線程來解決,這是治標(biāo)不治本的行為。我們應(yīng)該盡量在應(yīng)用端,也就是在編碼的過程中避免。
有哪些可以避免死鎖的方法呢?

死鎖的避免

1、在程序中,操作多張表時,盡量以相同的順序來訪問(避免形成等待環(huán)路)

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

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

4、盡量使用索引訪問數(shù)據(jù),避免沒有 where 條件的操作,避免鎖表;

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

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

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

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-07-13發(fā)表,共計2364字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 衡山县| 桐城市| 米易县| 曲阳县| 马鞍山市| 乌鲁木齐市| 麟游县| 江油市| 麦盖提县| 武川县| 乌鲁木齐县| 南澳县| 舒城县| 山阳县| 晋江市| 昌宁县| 巩义市| 临泽县| 东台市| 甘德县| 马尔康县| 佳木斯市| 南溪县| 贡觉县| 寿阳县| 新民市| 资溪县| 菏泽市| 鲁山县| 七台河市| 广德县| 洞头县| 鲜城| 秦安县| 连州市| 濮阳市| 伊通| 永善县| 泰来县| 特克斯县| 高密市|