Mysql数据库是否发生死锁?死锁的场景

本文探讨了Mysql的MyISAM和InnoDB存储引擎对于死锁的情况。MyISAM由于不支持事务,因此不会出现死锁,而InnoDB由于使用行锁和表锁,在特定情况下可能发生死锁,例如在并发的转账操作中。解决InnoDB死锁的一种方式是利用其内置的MVCC机制。

之前在面试中被问到此问题,在此做下笔记!
Mysql场景的存储引擎为MyISAM和InnoDB,我们以这两种来分析。

MyISAM

总:MyISAM中不会出现死锁。
在MyISAM中只用到表锁,不会有死锁的问题,锁的开销也很小,但是相应的并发能力很差。
解析:MyISAM不支持事务,即每次的读写都会隐性的加上读写锁,而我们知道读锁是共享的,写锁是独占的,意味着当一个Session在写时,另一个Session必须等待。

InnoDB

*总:InnoDB中会出现死锁。
InnoDB中实用了行锁和表锁,当未命中索引时,会自动退化为表锁。
我们举一个出现死锁的例子。
假设我们有个账户金额表 user_balance,包括两个字段,分别是 username 用户名、balance 余额。(例子来源极客时间“sql必知必会”)
某时刻用户 A 和用户 B 之间进行转账,同时数据库管理员想要查询 user_balance 表中的总金额:

SELECT SUM(balance) FROM user_balance

当我们读取的时候用了加行锁,可能会出现死锁的情况,若 B 开始执行给 A 转账:

UPDATE user_balance 
MySQL 中手动模拟死锁场景,通常涉及两个或多个事务互相等待对方持有的资源释放。为了构造这种场景,可以通过交叉加锁的方式,在事务中对不同的资源进行锁定,并保持事务未提交的状态。 ### 使用 InnoDB 行锁模拟死锁 MySQL 的 InnoDB 引擎支持行级锁和间隙锁,这使得在同一张表中不同行的并发操作成为可能,同时也为死锁提供了条件[^2]。以下是一个典型的死锁模拟示例: #### 示例:两个事务交叉更新不同记录导致死锁 ```sql -- 会话1 START TRANSACTION; UPDATE users SET balance = balance - 100 WHERE id = 1; -- 锁定id=1的记录 UPDATE users SET balance = balance + 100 WHERE id = 2; -- 等待会话2释放id=2的锁 COMMIT; -- 会话2 START TRANSACTION; UPDATE users SET balance = balance - 100 WHERE id = 2; -- 锁定id=2的记录 UPDATE users SET balance = balance + 100 WHERE id = 1; -- 等待会话1释放id=1的锁 COMMIT; ``` 在这个例子中,两个事务分别持有某一行的排他锁(X锁),同时尝试更新另一行。由于双方都在等待对方释放锁,最终形成死锁,InnoDB 存储引擎会检测到这种情况并自动回滚其中一个事务以解除死锁状态。 ### 使用唯一索引冲突引发死锁 除了行锁之外,还可以利用唯一索引的插入冲突来制造死锁。当多个事务尝试插入具有相同唯一键值的数据时,如果某个事务尚未提交,则后续事务会被阻塞,直到前一个事务完成。若这些事务相互依赖,则可能导致死锁发生[^5]。 #### 示例:通过唯一索引插入冲突模拟死锁 ```sql -- 会话1 START TRANSACTION; INSERT INTO test3 VALUES (119, 119, 30610); -- 插入数据 INSERT INTO test3 VALUES (119, 219, 30610); -- 阻塞,等待会话2释放锁 COMMIT; -- 会话2 START TRANSACTION; INSERT INTO test3 VALUES (119, 219, 30610); -- 插入与会话1冲突的数据 INSERT INTO test3 VALUES (6059, 6059, 6059); -- 阻塞,等待会话1释放锁 COMMIT; ``` 上述操作中,两个事务分别尝试插入具有相同唯一键的数据,导致彼此阻塞。如果两个事务都未提交,则形成死锁。 ### 死锁检测与处理 MySQL 的 InnoDB 引擎具备死锁检测机制,一旦发现死锁,会选择代价最小的事务进行回滚,从而打破死锁循环。用户可以通过查看 `SHOW ENGINE INNODB STATUS` 命令输出的信息,了解当前数据库中的死锁情况及其原因[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值