Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Vermeiden Sie Blockaden, indem Sie explizit bestellen

Obwohl Sie dies über straight_join tun können, können Sie die Sperren auch explizit für die gewünschten Zeilen erhalten, indem Sie select ...for update auf diejenige duplizieren, die Sie zuerst erhalten möchten.

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;

Da das Sperren in mehreren Schritten erfolgt, ist es möglich, dass Einträge in der Tabelle 'Farben' zwischen dem Einrichten der temporären Tabelle und dem Fertigstellen der Sperren für die beiden Tabellen geändert werden.

Das mag für Sie in Ordnung sein (z. B. wenn Sie nur vorhandene Einträge ändern möchten, wenn die Transaktion beginnt), könnte aber subtile Fehler verursachen, wenn Sie es nicht möchten.