淺談MySQL 有哪些死鎖場(chǎng)景
首先一起來(lái)復(fù)習(xí)一下死鎖的概念:死鎖是指兩個(gè)或者多個(gè)事務(wù)在同一資源上相互占用,并請(qǐng)求鎖定對(duì)方占用的資源,從而導(dǎo)致惡性循環(huán)的現(xiàn)象。
下面我們通過(guò)幾個(gè)實(shí)驗(yàn),來(lái)驗(yàn)證幾種死鎖場(chǎng)景。
1 環(huán)境準(zhǔn)備
use martin; drop table if exists dl; CREATE TABLE `dl` ( `id` int(11) NOT NULL AUTO_INCREMENT, `a` int(11) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `idx_c` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `dl_insert` ( `id` int(11) NOT NULL AUTO_INCREMENT, `a` int(11) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`id`), unique key `uniq_a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
insert into dl(a,b,c) values (1,1,1),(2,2,2); drop table if exists dl_1; create table dl_1 like dl; insert into dl_1 select * from dl;
2 同一張表下的死鎖
session1 | session2 |
begin; | begin; |
select * from dl where a=1 for update;…1 row in set (0.00 sec) | select * from dl where a=2 for update;…1 row in set (0.00 sec) |
select * from dl where a=2 for update;/* SQL1 */(等待) | |
(session2 提示死鎖回滾后,SQL1 成功返回結(jié)構(gòu)) | select * from dl where a=1 for update;ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
commit; | commit; |
session1 在等待 session2 釋放 a=2 的行鎖,而 session2 在等待 session1 釋放 a=1 的行鎖。兩個(gè) session 互相等待對(duì)方釋放資源,就進(jìn)入了死鎖狀態(tài)。
3 不同表下的死鎖
session1 | session2 |
begin; | begin; |
select * from dl where a=1 for update; … 1 row in set (0.00 sec) | select * from dl_1 where a=1 for update; … 1 row in set (0.00 sec) |
select * from dl_1 where a=1 for update;/* SQL2 */ 等待 | |
(session2 提示死鎖回滾后,SQL1 成功返回結(jié)構(gòu)) | select * from dl where a=1 for update; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
commit; | commit; |
這個(gè)實(shí)驗(yàn)也是兩個(gè) session 互相等待對(duì)方釋放資源,就進(jìn)入了死鎖狀態(tài)。
4 間隙鎖下的死鎖
session1 | session2 |
set session transaction_isolation='REPEATABLE-READ'; /* 設(shè)置會(huì)話(huà)隔離級(jí)別為 RR */ | set session transaction_isolation='REPEATABLE-READ'; /* 設(shè)置會(huì)話(huà)隔離級(jí)別為 RR */ |
begin; | begin; |
select * from dl where a=1 for update; … 1 row in set (0.00 sec) | select * from dl where a=2 for update; … 1 row in set (0.00 sec) |
insert into dl(a,b,c) values (2,3,3);/* SQL1 */ 等待 | |
(session2 提示死鎖回滾后,SQL1 成功返回結(jié)果) | insert into dl(a,b,c) values (1,4,4);/* SQL2 */ ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
commit; | commit; |
由于 RR 隔離級(jí)別下存在間隙鎖,可以知道 SQL1 需要等待 a=2 獲得的間隙鎖,而 SQL2 需要等待 a=1 獲得的間隙鎖,兩個(gè) session 互相等待對(duì)方釋放資源,就進(jìn)入了死鎖狀態(tài)。
5 INSERT 語(yǔ)句的死鎖
session1 | session2 | session3 |
begin; | ||
insert into dl_insert(a,b,c) value (3,3,3); | ||
insert into dl_insert(a,b,c) value (3,3,3);/* 等待 */ | insert into dl_insert(a,b,c) value (3,3,3);/* 等待 */ | |
rollback; | 執(zhí)行成功 | ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
這里需要注意的是,a 字段有唯一索引。當(dāng) session1 執(zhí)行完 insert 語(yǔ)句,會(huì)在索引 a=3 上加記錄鎖,當(dāng) session2 執(zhí)行同樣的 insert 語(yǔ)句時(shí),唯一鍵沖突,加上讀鎖;同樣 session3 也會(huì)加上讀鎖。
當(dāng) session1 回滾,session2 和 session3 都試圖繼續(xù)執(zhí)行插入操作,都要加上寫(xiě)鎖。此時(shí)兩個(gè) session 都要等待對(duì)方的行鎖,因此出現(xiàn)了死鎖。
一些死鎖場(chǎng)景就介紹到這里,當(dāng)然,也歡迎各位補(bǔ)充其他的一些死鎖場(chǎng)景。
到此這篇關(guān)于淺談MySQL 有哪些死鎖場(chǎng)景的文章就介紹到這了,更多相關(guān)MySQL 死鎖場(chǎng)景內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mysql數(shù)據(jù)庫(kù)清理binlog日志命令詳解
這篇文章主要給大家介紹了Mysql數(shù)據(jù)庫(kù)清理binlog日志命令的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Mysql具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09MySQL中配置文件my.cnf因權(quán)限問(wèn)題導(dǎo)致無(wú)法啟動(dòng)的解決方法
這篇文章主要給大家介紹了關(guān)于MySQL中配置文件my.cnf因權(quán)限問(wèn)題導(dǎo)致無(wú)法啟動(dòng)的解決方法,該無(wú)法啟動(dòng)的錯(cuò)誤提示代碼是:World-writable config file '/etc/my.cnf' is ignored,文中給出了詳細(xì)的解決方法,需要的朋友們下面來(lái)一起看看吧。2017-06-06基于Redo Log和Undo Log的MySQL崩潰恢復(fù)解析
這篇文章主要介紹了基于Redo Log和Undo Log的MySQL崩潰恢復(fù)流程,點(diǎn)進(jìn)來(lái)的小伙伴不要錯(cuò)過(guò)奧2021-08-08輕松掌握MySQL函數(shù)中的last_insert_id()
相信大家應(yīng)該都知道Mysql函數(shù)可以實(shí)現(xiàn)許多我們需要的功能,這篇文章介紹的Mysql函數(shù)Last_insert_id()就是其中之一,文章通過(guò)一個(gè)例子展開(kāi)來(lái)講,應(yīng)該更有助于大家的理解和學(xué)習(xí),有需要的朋友們下面來(lái)一起看看吧。2016-12-12MySQL中DATEDIFF()函數(shù)用法及返回周、月、年
這篇文章主要給大家介紹了關(guān)于MySQL中DATEDIFF()函數(shù)用法及返回周、月、年的相關(guān)資料,datediff()函數(shù)返回兩個(gè)日期之間的時(shí)間,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11將MySQL從MyISAM轉(zhuǎn)換成InnoDB錯(cuò)誤和解決辦法
原來(lái)自己用的是為了裝的, 所以在設(shè)置database usage(如下圖1)的時(shí)候按照discuz官方的建議,選的都是Non-Transactional Database Only(只支持MyISAM數(shù)據(jù)引擎的非事務(wù)數(shù)據(jù)庫(kù)),用MyISAM數(shù)據(jù)庫(kù),還沒(méi)涉及到需要InnoDB,因此打算直接不加載INNODB引擎。2011-09-09如何利用Mysql計(jì)算地址經(jīng)緯度距離實(shí)時(shí)位置
最近工作中遇到了一個(gè)附近門(mén)店的功能,下面這篇文章主要給大家介紹了關(guān)于如何利用Mysql計(jì)算地址經(jīng)緯度距離實(shí)時(shí)位置的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04