2017-10-08 1 views
0

Ich benutze diese Abfrage Zeilen zwischen konkurrierenden Arbeitern zu verteilen:Warum verursacht diese Abfrage einen Deadlock?

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

Manchmal warf sie auf eine Deadlock Ausnahme und ich habe es gerade neu gestartet. Aber mit einer ausreichend hohen Anzahl von Arbeitskräften beginnt es fast immer mit der Deadlock-Operation und bleibt in der Wiederholungsschleife hängen. Wie man es richtig umschreibt?

Antwort

0

Sie sollten processed Spalte indiziert haben und versuchen, diese Abfrage

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; 

Möglicherweise müssen Sie dies mehrere Male ausgeführt, bis Sie keine Null updated_id bekommen. Sie müssen mit der Situation umgehen, wenn es auch keine unbearbeiteten Datensätze gibt.

Alternative Ansatz:

jeden Prozess Unter der Annahme, hat eine einzigartige @process_Id und verarbeitet nur einen Datensatz zu einem Zeitpunkt und löschen oder zu verarbeitende -1 nach der Verarbeitung.

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

Sind Sie sicher, dass dies richtig funktionieren sollte? Was passiert, wenn die Zeile nach der Auswahl der Unterabfrage geändert wird, aber bevor die Aktualisierung erfolgt? Soll ich den Rückgabewert überprüfen und die Abfrage neu starten, wenn 0 Zeilen geändert werden? – Poma

+0

'UND verarbeitete = 0' sollte es verhindern. Ja, wenn 0 Zeilen geändert werden oder 0 zurückgegeben wird, sollten Sie die Abfrage neu starten. Möglicherweise müssen Sie hinzufügen, dass es eine Zeile mit "processed = 0" gibt, so dass Sie keine Endlosschleife haben. Alternative Vorgehensweise ist, ProcessId anstelle von -1 setzen, dann könnte es Dinge vereinfachen, in jedem Fall müssen Sie mit abgestürzten Prozessen beschäftigen. 'update tn set verarbeitet = wo verarbeitet = 0 Limit 1; Wählen Sie ID aus TN, wo verarbeitet = ' –

+0

' Allgemeiner Fehler: 1093 Sie können Zieltabelle 'Tabellenname' für die Aktualisierung in FROM-Klausel nicht angeben – Poma

Verwandte Themen