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