Mysql
 sql >> Base de données >  >> RDS >> Mysql

Évitez les impasses en commandant explicitement

Bien que vous puissiez le faire via straight_join, vous pouvez également obtenir explicitement les verrous sur les lignes souhaitées en dupliquant le select ...for update sur celui que vous souhaitez obtenir en premier.

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;

Comme le verrouillage se fait en plusieurs étapes, il serait possible que les entrées dans la table 'couleurs' soient modifiées entre le moment où vous configurez la table temporaire et le moment où vous avez fini d'obtenir les verrous sur les deux tables.

Cela peut vous convenir (c'est-à-dire si vous souhaitez uniquement modifier les entrées existantes, au démarrage de la transaction), mais cela peut entraîner des bogues subtils si ce n'est pas ce que vous voulez.