sql >> データベース >  >> RDS >> Mysql

明示的に注文してデッドロックを回避する

    Straight_joinを使用して実行できますが、最初に取得する行の更新のためにselect ...を複製することにより、必要な行のロックを明示的に取得することもできます。

    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つのテーブルのロックを取得し終えるまでの間に、テーブルの「色」のエントリを変更することができます。

    それはあなたにとっては問題ないかもしれませんが(つまり、トランザクションの開始時に既存のエントリのみを変更したい場合)、それがあなたの望むものでない場合、微妙なバグを引き起こす可能性があります。




    1. Linux上のasp.netコアアプリからテーブルを移行する方法

    2. ログオントリガーをドロップしようとすると「トリガーをドロップできません」エラーが発生しますか?これを試して。

    3. CentOS 7にApache、MySQL 8、またはMariaDB10とPHP7をインストールします

    4. MySQL、MariaDB、Percona Server、MongoDB、またはPostgreSQLのデプロイ-ClusterControlで簡単に