我试图防止代码中出现死锁,因为我可能会在项目的不同部分使用两者。
它们是否以相同的顺序锁定行?
嵌套
select * from `carts` where `carts`.`user_id` = ? and exists ( select * from `cart_items` where `carts`.`id` = `cart_items`.`cart_id` for update ) for update
分离
select * from `carts` where `carts`.`user_id` = ? for update
select * from `cart_items` where `cart_id` = ? for update
假设
START TRANSACTION
ie 在 it/them 之前,而 theCOMMIT
在之后,可以这样想:锁定从 时开始START
。或者这样...如果有两个事务正在进行
一个可以等待另一个完成(参见
lock_wait_timeout
)。相反,如果另一个人这样做
WHERE id (22, 11)
,则可能会出现僵局。在这种情况下,一个会回滚,另一个会继续完成。我怀疑带有嵌套的语句
EXISTS
比两个语句更快,因此我会尝试在两种情况下都执行前者。另外,请注意,有时 id 周围的“间隙”会被锁定。有时,间隙锁定要么没有意义,要么没有在 中清楚地显示出来
SHOW ENGINE INNODB STATUS;
。底线:做最坏的打算。准备好重放由于死锁而回滚的任何事务。