Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Evite dead lock ordenando explicitamente


Embora você possa fazer isso através de straight_join, você também pode obter explicitamente os bloqueios nas linhas que deseja duplicando o select ...for update no que deseja obter primeiro.
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;

Como o bloqueio é feito em várias etapas, seria possível que as entradas nas 'cores' da tabela fossem modificadas entre quando você configura a tabela temporária e quando você termina de obter os bloqueios nas duas tabelas.

Isso pode ser bom para você (ou seja, se você quiser apenas modificar as entradas existentes, quando a transação começar), mas pode causar bugs sutis se não for o que você deseja.