mysql 死锁-在事务中的什么时候获取锁?

yc0p9oo0  于 2023-01-16  发布在  Mysql
关注(0)|答案(1)|浏览(169)

动物桌

+----------+-------+
| name     | value |
+----------+-------+
| Aardvark |    10 |
+----------+-------+

鸟类表

+---------+-------+
| name    | value |
+---------+-------+
| Buzzard |    20 |
+---------+-------+

第一次会议:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT value FROM Animals WHERE name='Aardvark' FOR SHARE;
+-------+
| value |
+-------+
|    10 |
+-------+
1 row in set (0.00 sec)

第二次会议:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT value FROM Birds WHERE name='Buzzard' FOR SHARE;
+-------+
| value |
+-------+
|    20 |
+-------+
1 row in set (0.00 sec)

--waits to lock
mysql> UPDATE Animals SET value=30 WHERE name='Aardvark';

第一次会议:

mysql> UPDATE Birds SET value=40 WHERE name='Buzzard';
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

我们是否可以说,直到到达SQL语句之前都获得锁,或者说事务在此之前获得了所有锁?
很多人说我们必须获得我们将在整个事务中使用的所有(预期的)锁,以避免死锁,所以这个问题出现在我的脑海中。

mbyulnm0

mbyulnm01#

是的,行锁是在执行需要这些锁的SQL语句时按需获取的。
这意味着,如果两个会话并发运行,它们可能会以交叉方式而不是原子方式获取各自的锁。因此,它们可能都希望锁定已被另一个会话锁定的资源,在这种情况下,它们会创建死锁。
防止死锁的一个方法是在事务期间获取所有需要的锁--更重要的是,以原子方式获取锁。也就是说,所有锁必须一次获取,如果不成功,则释放所有锁。锁不能以交叉方式获取。
InnoDB并没有这样的特性,你可以使用MySQL的LOCK TABLES语句来锁定表。
另一种策略不是避免死锁,而是在死锁发生时从死锁中恢复。

相关问题