Ein Beitrag hier auf DBA.StackExchange ( Was sind die Best Practices für Trigger, um eine Revisionsnummer für Datensätze beizubehalten? ) Hat eine interessante (zumindest für mich interessante) Frage zur Leistung in MySQL aufgeworfen.
Der Kontext ist, dass wir für jede aktualisierte Zeile einen Datensatz in eine Tabelle einfügen möchten. Bevor die Zeile aktualisiert wird, möchten wir einen vorherigen Wert speichern und dann eine der Spalten (eine "Versions" -Spalte) erhöhen.
Wenn wir dies in einem Trigger tun, funktioniert es gut. Für MySQL sind die Trigger Zeile für Zeile , daher wäre dies eine einfache Lösung. Wählen Sie die aktuell in der Tabelle enthaltenen Daten aus, fügen Sie sie in die Protokollierungstabelle ein und aktualisieren Sie die Spalte "Version" in den neuen Daten.
Es ist jedoch möglich, diese Logik in eine gespeicherte Prozedur zu verschieben. Wenn Sie dies tun, führen Sie die Einfügung durch und erhöhen dann die Spalte "Version" in der Tabelle. Das Ganze würde auf Set basieren.
Wenn es also darum geht, diese Einfügung durchzuführen, wäre dies leistungsfähiger, wenn der satzbasierte Ansatz für gespeicherte Prozeduren oder ein triggerbasierter Ansatz verwendet wird?
Diese Frage bezieht sich auf MySQL (da es zeilenweise Trigger hat), obwohl sie auch für andere zeilenweise Trigger-DBMS gelten kann.
quelle
Antworten:
Der Einfachheit halber sind Trigger der richtige Weg, um jede Art von Nachverfolgung von Datenbankänderungen zu implementieren. Sie müssen jedoch wissen, was unter der Haube passiert, wenn Sie Trigger verwenden.
Laut MySQL Stored Procedure Programming wird auf Seite 256 unter der Überschrift "Trigger Overhead" Folgendes angegeben:
Eine erweiterte Erläuterung des Trigger-Overheads finden Sie auf den Seiten 529-531. Der abschließende Punkt aus diesem Abschnitt lautet wie folgt:
Nicht im Buch erwähnt ist ein weiterer Faktor bei der Verwendung von Triggern: Wenn es um die Überwachungsprotokollierung geht, beachten Sie bitte, bei was Sie Daten anmelden. Ich sage dies, weil jedes INSERT in einer MyISAM-Tabelle eine vollständige Tabellensperre während des INSERT erzeugt, falls Sie sich für die Anmeldung bei einer MyISAM-Tabelle entscheiden. Dies kann zu einem schwerwiegenden Engpass in einer Umgebung mit hohem Datenverkehr und hohen Transaktionen werden. Wenn der Trigger gegen eine InnoDB-Tabelle gerichtet ist und Sie Änderungen in MyISAM innerhalb des Triggers protokollieren, wird die ACID-Konformität heimlich deaktiviert (dh Blocktransaktionen auf Autocommit-Verhalten reduziert), was nicht rückgängig gemacht werden kann.
Bei Verwendung von Triggern für InnoDB-Tabellen und Protokollierung von Änderungen
Auf diese Weise können Überwachungsprotokolle wie Haupttabellen von COMMIT / ROLLBACK profitieren.
In Bezug auf die Verwendung gespeicherter Prozeduren müssten Sie die gespeicherte Prozedur an jedem Punkt der DML sorgfältig gegen die zu verfolgende Tabelle aufrufen. Man könnte leicht die Protokollierung von Änderungen angesichts von Zehntausenden von Zeilen Anwendungscode übersehen. Wenn Sie einen solchen Code in einen Trigger einfügen, werden alle diese DML-Anweisungen nicht mehr gefunden.
VORBEHALT
Je nachdem, wie komplex der Auslöser ist, kann es sich dennoch um einen Engpass handeln. Wenn Sie Engpässe bei der Überwachungsprotokollierung reduzieren möchten, können Sie Folgendes tun. Es wird jedoch eine kleine Änderung der Infrastruktur erforderlich sein.
Erstellen Sie mit Standardhardware zwei weitere DB-Server
Dadurch wird der Server reduziert, um die Schreib-E / A in der Hauptdatenbank (MD) aufgrund der Überwachungsprotokollierung zu reduzieren. So können Sie es erreichen:
Schritt 01) Aktivieren Sie die binäre Protokollierung in der Hauptdatenbank.
Schritt 02) Richten Sie MySQL (dieselbe Version wie MD) mit einem kostengünstigen Server mit aktivierter binärer Protokollierung ein. Dies wird DM sein. Richten Sie die Replikation von MD auf DM ein.
Schritt 03) Richten Sie MySQL (dieselbe Version wie MD) mit einem zweiten kostengünstigen Server mit deaktivierter binärer Protokollierung ein. Richten Sie jede Prüftabelle für die Verwendung von --replicate-do-table ein . Dies wird AU sein. Richten Sie die Replikation von DM nach AU ein.
Schritt 04) mysqldump die Tabellenstrukturen von MD und laden Sie es in DM und AU.
Schritt 05) Konvertieren Sie alle Audit-Tabellen in MD, um die BLACKHOLE-Speicher-Engine zu verwenden
Schritt 06) Konvertieren Sie alle Tabellen in DM und AU, um die BLACKHOLE-Speicher-Engine zu verwenden
Schritt 07) Konvertieren Sie alle Audit-Tabellen in AU, um die MyISAM-Speicher-Engine zu verwenden
Wenn Sie fertig sind
Dadurch werden Überwachungsinformationen auf einem separaten DB-Server gespeichert und die normalerweise auftretende Verschlechterung der Schreib-E / A verringert.
quelle
Hier ist ein Ansatz, um dieses Update in großen Mengen durchzuführen.
Für dieses Beispiel
Gehen Sie wie folgt vor, um table_A_Keys2Update zu erstellen:
Nachdem Sie table_A_Keys2Update mit den IDs gefüllt haben, deren Revisionsnummer erhöht werden muss, führen Sie das folgende UPDATE JOIN aus, um die Revisionsnummer aller Zeilen zu erhöhen, deren ID sowohl in table_A als auch in table_A_Keys2Update enthalten ist:
Diese einzeilige Abfrage kann einen Trigger und eine gespeicherte Prozedur ersetzen.
Optional können Sie diese eine Abfrage in eine gespeicherte Prozedur einfügen und auf Wunsch aufrufen.
quelle