2017-05-19 3 views
0

Ich habe ein Problem mit mysql und meine Nodejs App zu bekommen, gut zusammen zu spielen. Im Grunde habe ich zwei Nodejs "Clients", die MySQL-Tabelle für 50 Zeilen von Daten abfragen. Ich möchte jedoch nicht, dass sie dieselben 50 Zeilen abfragen. Sobald ein Client über 50 Datenzeilen verfügt, führt er einige grundlegende Operationen aus und startet einige Bash-Skripte. Das kann einige Sekunden dauern. Alle 50 Datenzeilen werden in der Tabelle aktualisiert, um anzuzeigen, dass diese Zeilen auf diesem Client "in Verwendung" sind.Mehrere Prozesse Abfragen von MySQL und Aktualisieren von Daten

Das Problem ist, gibt es Situationen, in denen beide Clients zur gleichen Zeit anfordern und die gleichen 50 Zeilen erhalten. Wie kann/kann ich ein innodb-Lock sicher verwenden, um zu verhindern, dass diese Zeilen von einem anderen Client gelesen/verwendet werden? Auch wenn es ein paar Sekunden dauern kann, um sicherzustellen, dass die Zeilendaten die Skripts erfolgreich hochgespielt haben?

Ich bin irgendwie ratlos und brauche ein paar Hinweise.

Antwort

0

können Sie die redis-Sperre verwenden, um eine solche Aufgabe auszuführen.

zB: Seitengröße = 50; wenn Sie Datensätze von 100 erhalten möchten; Größe = 50; Sie müssen zum Beispiel Schloss locks:row:100 erwerben.

https://www.npmjs.com/package/redlock

const resource = 'locks:row:100' 
const ttl = 1000 

redlock.lock(resource, ttl).then(function(lock) { 
    // DO STUFF 

    return lock.unlock() 
     .catch(function(err) { 
      console.error(err) 
     }) 
}) 
1

Was Sie suchen ist

SELECT columnName FROM tableName FOR UPDATE; 

Dies wird eine Reihe auswählen und sperren, so eine andere gleichzeitige Verbindung kann es nicht auswählen.

Siehe doc MySql Here

+0

'SELECT ... FOR UPDATE' ist, was ich erforscht habe. Müsste ich die Anrufe in einer Transaktion tätigen? Gibt es eine bessere Möglichkeit, den "UPDATE" -Teil für 50 Zeilen gleichzeitig auszuführen? – Jerry

0

Eine andere mögliche Lösung Sie erwähnen.

Alle 50 Datenzeilen werden in der Tabelle aktualisiert, um anzuzeigen, dass die Zeilen auf diesem Client "in Verwendung" sind.

Ich frage mich, wie genau Sie diesen Schritt tun .. es scheint richtig gemacht, diese Methode sollte sich als wirksam erweisen.

würde ich zuerst

UPDATE tableName 
SET lockColumnName='jnodeClientGUID' 
WHERE lockColumnName IS NULL 
LIMIT 50 

Dann könnten Sie

SELECT * 
FROM tableName 
WHERE lockColumnName = 'jnodeClientGUID' 

Sie würden in geeigneter Weise die Entriegelung der Datensätze verwalten dann tun Saftey haben, aber das Sie den Effekt würde die Verriegelungs Aufzeichnungen über viele Sekunden und sollte Probleme des Race Condition entfernen.

Obwohl zugegebenermaßen bin ich nicht zuversichtlich, dass dies der effizienteste Weg ist.