我想显式地提供有关MySql InnoDB如何获取行锁的命令。如果这是可能的,则不应有任何死锁而已。 (如果我们遵循惯例。)

首先,数据库应按升序锁定在表“模型”中找到的所有行。然后,第二个表“颜色”中的所有行应按升序锁定。有没有一种方法可以控制数据库先锁定表“模型”然后锁定“颜色”?

举个例子:

start transaction;
select *
from models m
join colors c on c.model_id = m.id
where c.id IN (101, 105, 106)
order by m.id asc, c.id asc
for update;

最佳答案

尽管您可以通过straight_join来做到这一点,但是您也可以通过将select ... for复制到要首先获取的行上,来显式地获取所需行的锁。

CREATE TEMPORARY TABLE colorsToUpdate (
     colorID BIGINT(20) NOT NULL,
     modelID BIGINT(20) NOT NULL
);

insert into colorsToUpdate ( colorID, modelID)
SELECT  id, model_id
FROM    colors
where id in (101, 105, 106);

#This will try to acquire lock on models
select m.* from models m
join colorsToUpdate c
on c.modelID = m.id
for UPDATE;

#this will try to get locks on models, and colors.
select m.*, c.*
from colorsToUpdate u
left join models m
on u.modelID = m.id
join colors c
on u.colorID = c.ID
order by m.id asc, c.id asc
for update;

# do your data modification here.

drop table colorsToUpdate;

由于锁定是分多个步骤完成的,因此在设置临时表与完成获取两个表的锁定之间可能会修改表“colors”中的条目。

这可能对您来说没问题(例如,如果您只想在事务开始时修改现有条目),但如果不是您想要的,则可能会导致细微的错误。

关于mysql - 通过显式订购避免死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10838517/

10-13 22:10