MySQL单条语句是否原子执行?两连接按不同顺序锁表是否会引发死锁?
MySQL相关问题解答
问题1:MySQL是否会原子性地执行单条语句?
绝对会!MySQL对单条SQL语句的执行是保证原子性的——要么这条语句的所有操作全部完成,要么全部不执行,不会出现部分成功部分失败的情况。
举几个实际场景的例子:
- 执行批量插入语句
INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'),哪怕第二条数据存在主键重复的问题,整个INSERT操作都会失败,不会只插入第一条数据。 - 执行更新语句
UPDATE accounts SET balance = balance - 100 WHERE id = 1,不管账户原本余额是否充足,要么余额成功扣减,要么因为约束限制等原因完全不执行,绝不会出现扣减一半的中间状态。
这里需要区分「单条语句的原子性」和「事务的原子性」:事务是把多条语句打包成一个原子执行单元,但单条语句本身,哪怕你没显式开启事务,MySQL也会保证它的原子性——哪怕是MyISAM这种不支持事务的存储引擎,单条语句的操作也是原子的,因为它会通过表锁来避免执行过程被打断。
问题2:两个连接按不同顺序锁表会导致死锁吗?
答案是不会。
这得从MySQL的LOCK TABLES机制说起:当你执行LOCK TABLES table1 WRITE, table2 WRITE这类多表锁语句时,MySQL并不是按照你写的顺序逐个获取锁的。它会先将你指定的所有表按字典序排序,然后按照这个统一的顺序来获取锁。
回到你的场景:
- 连接1请求锁A和B,MySQL会先尝试获取A的写锁,再获取B的写锁;
- 连接2请求锁B和A,MySQL同样会先尝试获取A的写锁,再获取B的写锁。
这样一来,两个连接都会先竞争A的锁:谁先拿到A的锁,就会继续去拿B的锁,拿到后完成锁表操作;另一个连接因为拿不到A的锁,会一直等待,直到前一个连接释放所有锁(执行UNLOCK TABLES或者断开连接)。
不会出现「连接1拿着A等B,连接2拿着B等A」的经典死锁场景,因为MySQL的锁表逻辑从根源上避免了这种循环等待的可能。
内容的提问来源于stack exchange,提问作者Rajat Aggarwal
相关产品推荐
相关产品推荐

