7

MySqlInnoDBが行のロックを取得する方法を明示的に指定したいと思います。これが可能であれば、デッドロックが停止するだけではいけません。(慣例に従う場合。)

まず、データベースはテーブル「モデル」にあるすべての行を昇順でロックする必要があります。次に、2番目のテーブル「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;
4

1 に答える 1

1

Straight_join を介して行うこともできますが、最初に取得したい行の 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;

ロックは複数のステップで行われるため、一時テーブルを設定してから 2 つのテーブルのロックを取得し終えるまでの間に、テーブル 'colors' のエントリが変更される可能性があります。

これで問題ないかもしれませんが (つまり、トランザクションの開始時に既存のエントリを変更するだけの場合)、それが望ましくない場合は微妙なバグが発生する可能性があります。

于 2012-08-16T06:02:41.070 に答える