2017-10-08 3 views
0

私は同時労働者間の行を配布するために、このクエリを使用します。このクエリでデッドロックが発生するのはなぜですか?

SET @update_id := 0; 
UPDATE tablename 
    SET processed = -1, id = (SELECT @update_id := id) 
    WHERE processed = 0 
    LIMIT 1 
SELECT @update_id as id; 

時にはそれがデッドロック例外を投げたし、私はそれを再起動しました。しかし、労働者数が十分に高いと、ほとんど毎回デッドロックが発生し、リトライ・ループに巻き込まれるようになります。正しく書き直すには?

答えて

0

あなたはどれもゼロupdated_idを取得するまで、あなたはこれを数回に実行する必要がありますprocessed列がインデックスがあり、

SET @update_id := (SELECT id FROM tablename t WHERE processed = 0 LIMIT 1); 
SET @updated_id := 0; 
UPDATE tablename 
    SET processed = -1, id = (SELECT @updated_id := id) 
WHERE 
     id = @update_id 
     AND processed = 0; 

SELECT @updated_id as id; 

このクエリを試してみてください。未処理のレコードがない場合も、状況を処理する必要があります。

代替アプローチ:各プロセスを仮定

は一意@process_Idを有しており、それは、一度に1件のレコードを処理し、それを削除したり、処理後に-1加工セット。

UPDATE tablename SET processed = @process_id WHERE processed = 0 LIMIT 1;  
SELECT id FROM tablename t WHERE processed = @process_id; 
+0

これは正しく動作するはずですか? selectサブクエリが返された後、更新が行われる前に行が変更された場合はどうなりますか? 0行が変更された場合、戻り値をチェックして再クエリを実行する必要がありますか? – Poma

+0

'AND processed = 0'はそれを防ぐべきです。 はい、0行が変更された場合や0が返された場合は、クエリを再起動する必要があります。 'processed = 0'の行があることを確認する必要があるかもしれないので、無限ループはありません。 代わりに、-1の代わりにProcessIdを設定すると、事態を簡単にすることができます。いずれの場合も、クラッシュしたプロセスに対処する必要があります。 'update tn set processed = 処理済み= 0の制限1; どこから処理されたかを選択します。= ' –

+0

'一般的なエラー:1093 FROM句で更新対象テーブル 'tablename'を指定することはできません。 ' – Poma

関連する問題