Mysql 通过显式排序避免死锁

Mysql 通过显式排序避免死锁,mysql,sql,locking,innodb,pessimistic-locking,Mysql,Sql,Locking,Innodb,Pessimistic Locking,我想明确地提供一个关于MySql InnoDB应该如何获取行锁的顺序。如果这是可能的,不应该有任何死锁只是失速。(如果我们遵循惯例。) 首先,数据库应该按升序锁定表“models”中的所有行。然后,第二个表“colors”中的所有行都应按升序锁定。是否有一种方法可以控制数据库先锁定表“模型”,然后锁定“颜色” 例如: start transaction; select * from models m join colors c on c.model_id = m.id where c.id IN

我想明确地提供一个关于MySql InnoDB应该如何获取行锁的顺序。如果这是可能的,不应该有任何死锁只是失速。(如果我们遵循惯例。)

首先,数据库应该按升序锁定表“models”中的所有行。然后,第二个表“colors”中的所有行都应按升序锁定。是否有一种方法可以控制数据库先锁定表“模型”,然后锁定“颜色”

例如:

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;

尽管可以通过直接连接来实现,但也可以通过在要首先获取的行上复制select…for update来显式获取所需行的锁

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;
由于锁定是分多个步骤完成的,因此在设置临时表和完成两个表上的锁定之间,可以修改表“颜色”中的条目


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

选择没有锁,请您提供更多信息好吗?@Sebas:OP问题中的示例使用了锁。我明白了,首先,需要更新什么?型号、颜色还是两者都有?@Sebas:我想更新两个表;事实上,模型和颜色之间存在父子关系。如果mysql支持这样的东西,我会感到惊讶。您的问题是假定进行排序的特定方法是嵌套循环。我建议您在单个事务中独立更新这两个表。