一个事务自身的行为是可能造成死锁,以前一直没有找到合适的例子,下面这种情况就会造成死锁。
客户端A操作:
CREATE TABLE t (i INT) ENGINE = InnoDB;
INSERT INTO t (i) VALUES(1);
START TRANSACTION;
SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
START TRANSACTION;
DELETE FROM t WHERE i = 1;
客户端A操作:
mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
注意这样的操作顺序会造成死锁,下面简单的分析一下死锁的原因
1 A新建一个表后,对这张表进行了一个读操作,获得一个读锁,现在这个事务没有释放。
2 B要删除该表中的数据,需要得到一个写锁,这个时候因为有了读锁,写锁不能分派,所以这个请求放在写锁的请求队列上。
3 A要删除数据,也需要得到一个写锁,从2可以知道,写锁队列不为空,所以继续这个请求放到写锁队列上。
这样分析,麻烦就来了,从3可以知道,A被阻塞在写锁队列上,然而写锁能够分派的一个前提条件是读锁能够释放,也就是A事务可以提交,但是现在A事务因为有了一个写锁在写锁队列上,所以A就不可能正常提交。所以造成了死锁。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合终身会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步