Mysql5.7并發(fā)插入死鎖問(wèn)題解決
死鎖的產(chǎn)生條件
互斥、請(qǐng)求和保持、不可剝奪、循環(huán)等待
MySQL鎖類型

死鎖復(fù)現(xiàn)
環(huán)境:Mysql 5.7版本,Innodb引擎,可重復(fù)度隔離級(jí)別
并發(fā)場(chǎng)景下使用duplicate key update插入或更新數(shù)據(jù)可能會(huì)造成死鎖,下面就產(chǎn)生死鎖的條件進(jìn)行模擬
表:
CREATE TABLE `song_rank` ( `id` int(11) NOT NULL AUTO_INCREMENT, `songId` int(11) NOT NULL, `weight` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `songId_idx` (`songId`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
隔離級(jí)別:可重復(fù)度(RR)
select @@tx_isolation;

預(yù)先插入兩條數(shù)據(jù)
| id | songId | weight |
|---|---|---|
| 1 | 10 | 30 |
| 2 | 20 | 30 |

關(guān)閉事務(wù)自動(dòng)提交:
select @@autocommit; set autocommit=0;

死鎖場(chǎng)景一:
記錄鎖循環(huán)等待:如果兩個(gè)事務(wù)并發(fā)讀寫相同行,會(huì)由于加鎖時(shí)機(jī)的不同而造成死鎖,導(dǎo)致其中一個(gè)事務(wù)執(zhí)行失?。╩ysql可以配置自動(dòng)檢測(cè)死鎖然后自動(dòng)斷開其中一個(gè)innodb_deadlock_detect)
## 事務(wù)一 # 第一步執(zhí)行 begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; # 第三步執(zhí)行 insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; ## 事務(wù)二 # 第二步執(zhí)行 begin; insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; # 第四步執(zhí)行 insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1;
| 執(zhí)行步驟 | 事務(wù)一 | 事務(wù)二 | 鎖狀態(tài) |
|---|---|---|---|
| 第一步 | begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事務(wù)一對(duì)17新增記錄鎖 | |
| 第二步 | begin;insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; | 事務(wù)二對(duì)16新增記錄鎖 | |
| 第三步 | insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; | 事務(wù)一等待事務(wù)二釋放16的記錄鎖 | |
| 第四步 | insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事務(wù)二等待事務(wù)一釋放17的記錄鎖,出現(xiàn)死鎖 |
死鎖場(chǎng)景二:
記錄鎖、間隙鎖循環(huán)等待:在并發(fā)插入、更新同一條數(shù)據(jù)時(shí),一個(gè)事務(wù)獲取了記錄鎖,一個(gè)事務(wù)在等待記錄排他鎖,則事務(wù)在執(zhí)行插入獲取間隙鎖是會(huì)造成死鎖。
# 事務(wù)一 # 第一步執(zhí)行 begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; # 第四步執(zhí)行 rollback; # 事務(wù)二 # 第二步執(zhí)行 begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; # 事務(wù)三 # 第三步執(zhí)行 begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; # 出現(xiàn)死鎖
| 執(zhí)行步驟 | 事務(wù)一 | 事務(wù)二 | 事務(wù)三 | 鎖狀態(tài) |
|---|---|---|---|---|
| 第一步 | begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事務(wù)一對(duì)17新增記錄鎖 | ||
| 第二步 | begin;insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事務(wù)二等待17記錄鎖 | ||
| 第三步 | begin;insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事務(wù)三等待17的記錄鎖 | ||
| 第四步 | rollback; | 事務(wù)二獲取17記錄鎖,事務(wù)三等待17記錄鎖,事務(wù)一獲取間隙鎖時(shí)需要等待事務(wù)三釋放17記錄鎖,出現(xiàn)死鎖 |
避免死鎖
控制并發(fā)寫入和更新;
先執(zhí)行插入,捕獲插入異常并處理更新數(shù)據(jù);
到此這篇關(guān)于Mysql5.7并發(fā)插入死鎖問(wèn)題解決的文章就介紹到這了,更多相關(guān)Mysql5.7并發(fā)插入死鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL容災(zāi)備份的實(shí)現(xiàn)方案
進(jìn)行MySQL的容災(zāi)備份是確保數(shù)據(jù)安全和業(yè)務(wù)連續(xù)性的關(guān)鍵步驟,容災(zāi)備份可以分為本地備份和遠(yuǎn)程備份,主要包括邏輯備份和物理備份兩種方式,下面就來(lái)具體介紹一下2025-08-08
MySQL使用MRG_MyISAM(MERGE)實(shí)現(xiàn)分表后查詢的示例
這篇文章主要介紹了MySQL使用MRG_MyISAM(MERGE)實(shí)現(xiàn)分表后查詢的示例,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫(kù),感興趣的朋友可以了解下2020-12-12
解決phpstudy無(wú)法啟動(dòng)MySQL服務(wù)的三種方法小結(jié)
本文主要介紹了光速解決phpstudy無(wú)法啟動(dòng)MySQL服務(wù)的三種方法小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-09-09
MyBatis攔截器實(shí)現(xiàn)分頁(yè)功能的實(shí)現(xiàn)方法
這篇文章主要介紹了MyBatis攔截器實(shí)現(xiàn)分頁(yè)功能的實(shí)現(xiàn)方法的相關(guān)資料,希望通過(guò)本文大家能夠?qū)崿F(xiàn)這樣的方法,需要的朋友可以參考下2017-10-10
MySQL實(shí)戰(zhàn)文章(非常全的基礎(chǔ)入門類教程)
半個(gè)月時(shí)間把MySQL重新鞏固了一遍,梳理了一篇幾萬(wàn)字超硬核文章,想學(xué)習(xí)mysql的朋友可以看看2023-05-05

