Mysql5.7并發(fā)插入死鎖問題解決
死鎖的產(chǎn)生條件
互斥、請求和保持、不可剝奪、循環(huán)等待
MySQL鎖類型
死鎖復(fù)現(xiàn)
環(huán)境:Mysql 5.7版本,Innodb引擎,可重復(fù)度隔離級別
并發(fā)場景下使用duplicate key update插入或更新數(shù)據(jù)可能會造成死鎖,下面就產(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
隔離級別:可重復(fù)度(RR)
select @@tx_isolation;
預(yù)先插入兩條數(shù)據(jù)
id | songId | weight |
---|---|---|
1 | 10 | 30 |
2 | 20 | 30 |
關(guān)閉事務(wù)自動提交:
select @@autocommit; set autocommit=0;
死鎖場景一:
記錄鎖循環(huán)等待:如果兩個事務(wù)并發(fā)讀寫相同行,會由于加鎖時機(jī)的不同而造成死鎖,導(dǎo)致其中一個事務(wù)執(zhí)行失?。╩ysql可以配置自動檢測死鎖然后自動斷開其中一個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ù)一對17新增記錄鎖 | |
第二步 | begin;insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; | 事務(wù)二對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)死鎖 |
死鎖場景二:
記錄鎖、間隙鎖循環(huán)等待:在并發(fā)插入、更新同一條數(shù)據(jù)時,一個事務(wù)獲取了記錄鎖,一個事務(wù)在等待記錄排他鎖,則事務(wù)在執(zhí)行插入獲取間隙鎖是會造成死鎖。
# 事務(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ù)一對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ù)一獲取間隙鎖時需要等待事務(wù)三釋放17記錄鎖,出現(xiàn)死鎖 |
避免死鎖
控制并發(fā)寫入和更新;
先執(zhí)行插入,捕獲插入異常并處理更新數(shù)據(jù);
到此這篇關(guān)于Mysql5.7并發(fā)插入死鎖問題解決的文章就介紹到這了,更多相關(guān)Mysql5.7并發(fā)插入死鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL decimal unsigned更新負(fù)數(shù)轉(zhuǎn)化為0
這篇文章主要介紹了MySQL decimal unsigned更新負(fù)數(shù)轉(zhuǎn)化為0,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-12-12Windows系統(tǒng)下MySQL無法啟動的萬能解決方法
這篇文章主要給大家介紹了關(guān)于Windows系統(tǒng)下MySQL無法啟動的萬能解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12