Ich habe eine Tabelle in MySQL, die eine Warteschlange von zu verarbeitenden Links darstellt. Die Links werden einzeln von einer externen App verarbeitet und am Ende gelöscht. Dies ist eine Warteschlange mit hohem Volumen, und ich habe mehrere Instanzen der Verarbeitungs-App, die auf mehrere Server verteilt sind.
Wie kann ich sicherstellen, dass jeder Datensatz nur von einer App ausgewählt wird? Gibt es eine Möglichkeit, den Datensatz zu kennzeichnen / zu sperren?
Im Moment erlaube ich jeder Instanz, nur einen bestimmten Satz von Datensätzen (basierend auf dem MOD ihrer ID) aufzunehmen, um zu vermeiden, dass zwei oder mehr denselben Link abrufen. Dies ist jedoch keine transparente Möglichkeit, die Warteschlangenverarbeitung zu erhöhen Geschwindigkeit nur durch Hinzufügen neuer Instanzen.
Antworten:
Erstens: MySQL ist eine der schlechtesten Software, um dies zu implementieren, insbesondere wenn es sehr dynamisch ist. Der Grund dafür ist, dass Engines wie MEMORY und MyISAM nur vollständige Tabellensperren haben, während geeignetere Engines wie InnoDB eine höhere Schreibstrafe haben (um ACID-Eigenschaften bereitzustellen) und für den Zugriff auf Datensätze optimiert sind, die räumlich und zeitlich geschlossen sind (diese sind im Speicher festgelegt) ). Es gibt auch kein gutes Änderungsbenachrichtigungssystem für MySQL - es muss als Abfrage implementiert werden. Es gibt Dutzende von Softwareteilen, die für diese Aufgabe optimiert sind .
Trotzdem habe ich gesehen, dass diese Art des Zugriffs erfolgreich implementiert wurde, wenn die Leistungs- / Effizienzanforderungen nicht sehr hoch sind. Viele Menschen können es sich nicht leisten, nur für einen kleinen Teil der Geschäftslogik eine vollständig separate Technologie einzuführen und zu warten.
SELECT FOR UPDATE
ist das, wonach Sie suchen - lesen Sie die Serialisierung. Während ein UPDATE / DELETE die Zeile während einer laufenden MYSQL-Transaktion immer sperrt, möchten Sie möglicherweise eine große Transaktion vermeiden, während der Prozess ausgeführt wird.MySQL sorgt dafür, dass alle gleichzeitigen Auswahlen bis auf eine gesperrt werden, wenn Zeilen ausgewählt werden. Da dies zu vielen gesperrten Verbindungen gleichzeitig führen kann, halten Sie die anfängliche Transaktion so klein wie möglich und versuchen Sie, mehr als eine Zeile gleichzeitig zu verarbeiten.
quelle
Wie ich in diesem Artikel erklärt habe , hat MySQL 8 die Unterstützung für SKIP LOCKED und NO WAIT eingeführt.
SKIP LOCKED ist nützlich zum Implementieren von Jobwarteschlangen (auch als Stapelwarteschlangen bezeichnet), damit Sie Sperren überspringen können, die bereits durch andere gleichzeitige Transaktionen gesperrt sind.
NO WAIT ist nützlich, um zu vermeiden, dass gewartet wird, bis eine gleichzeitige Transaktion die Sperren aufhebt, an denen wir auch interessiert sind. Ohne KEINE WARTUNG müssen wir entweder warten, bis die Sperren freigegeben werden (zum Festschreibungs- oder Freigabezeitpunkt durch die Transaktion, die derzeit die Sperren enthält), oder die Sperrenerfassung läuft ab. Daher wirkt NO WAIT wie ein Sperrzeitlimit mit einem Wert von
0
.Weitere Informationen zu SKIP LOCK und NO WAIT finden Sie in diesem Artikel .
quelle
Ich habe etwas Ähnliches mit Offline-DBCC-Prüfungen gemacht (zwei Server, die Sicherungswiederherstellungen durchführen, und dann eine DBCC-Prüfung). Ein Server sammelt gestern alle 31 Server-Backups und stellt sie in eine Warteschlange. Dann ziehen dieser Server und ein anderer Server aus dieser Warteschlange. Obwohl es nicht viele Server gibt, sollte die Methode dieselbe bleiben: Lassen Sie den Anwendungsserver eine Aktualisierungsabfrage für die Warteschlange ausführen, um ein Datums- / Zeitfeld und ein Feld "Anwendungsserver" mit dem Namen des Anwendungsservers oder besser noch der numerischen ID zu aktualisieren. Dies führt zu einer Sperre. Wenn bereits eine Sperre von einem anderen Server vorhanden ist, der die nächste Zeile erhält, wird diese blockiert und es wird gewartet, bis die andere App die nächste Zeile erhalten hat. Sie möchten dann, dass die App den neuesten Datensatz aus der Warteschlange für das App-Feld zurückzieht und die gewünschten Informationen abruft. Verwenden von MySQL '
quelle