MySQL: Queries für bestimmte Benutzer (nicht) loggen

Ich hatte nun mit dem Szenario zu kämpfen, dass ein externes Programm in einer Datenbank schreibt; das Unternehmen hinter dem externen Programm allerdings nicht sagen konnte/wollte, welche Felder, welche Queries, etc.

Nun sollten wir was an der Datenbank anpassen – und müssen die Info dennoch dafür haben. Gott sei Dank ist dies relativ simple machbar, solange wir root-Zugriff auf die Datenbank haben.

Der Fahrplan:

  • wir loggen alle Queries (weil wir nur alles oder nichts loggen können)
  • wir löschen Einträger aus der Log-Tabelle jede Stunde nach einem Schema
  • und damit haben wir nur das, was wir benötigen

In meinem Fall gibt es drei Benutzer in der Anwendung: „root“, „application“ und „externaltool“. „root“ ist mein root-Benutzer, der führt nur Queries aus die ich tatsächlich händisch eingebe, für den brauche ich die Logs nicht. „application“ ist meine Anwendung, die kenne ich, da weiß ich was die tut. Und „externaltool“ macht irgendwas.

Das Löschen können wir in zwei Richtungen machen, die beide den selben Effekt haben.

  1. entweder löschen wir alle Einträge von „root“ und „application“,
  2. oder nur die wo der Benutzer nicht „externaltool“ ist

Bei beiden ist der Effekt der selbe – nur Queries von „externaltool“ werden angezeigt. Je nachdem, was du für eine Anzahl an Benutzern hast, kannst du den einen oder anderen Weg gehen. Ich habe mich für den ersten entschieden.

First of all: aktivieren vom Loggen von Queries. Dazu gehen wir als root in die Datenbank und hauen mal folgende Statements raus:

SET GLOBAL log_output = 'table';
SET GLOBAL general_log = 'ON';

Wechseln wir per in die Datenbank mysql und schauen mal nach, was da Phase ist:

USE mysql;
SELECT * FROM general_log;

Uuunnnddd – wir sehen tatsächlich eine Tabelle, in der steht, dass root [root] @ localhost [] die beiden Queries ausgeführt hat, die wir gerade eingegeben haben. Nice.

Nun kommen wir zu dem schwierigerem Teil – das zu filtern. Der Plan:

  • jede Stunde deaktivieren wir logging kurz,
  • benennen die Tabelle general_log um (damit wir drin schreiben können)
  • löschen die Felder raus die wir nicht brauchen
  • benennen sie zurück um
  • und aktivieren Logging wieder

Damit wir das „jede Stunde“ hinbekommen, aktivieren wir den event_scheduler in MySQL:

SET GLOBAL event_scheduler = 'ON';

Unter der Annahme, dass wir weiterhin in der Datenbank mysql sind, erstellen wir mit folgendem Befehl ein neues Event, was o.g. Aufgaben jede Stunde für uns übernimmt:

CREATE EVENT delete_some_logs
  ON SCHEDULE
    EVERY 1 HOUR
  COMMENT 'Loeschen aller Logs von root und root_ext'
  DO
    BEGIN
      SET GLOBAL general_log = 'OFF';
      RENAME TABLE mysql.general_log TO mysql.general_log_temp;
      DELETE FROM mysql.general_log_temp
        WHERE user_host LIKE '%[root]%';
      DELETE FROM mysql.general_log_temp
        WHERE user_host LIKE '%[application]%';
      RENAME TABLE mysql.general_log_temp TO mysql.general_log;
      SET GLOBAL general_log = 'ON';
    END |

DELIMETER ;

Nun warten wir eine Stunde; und die Datenbank sollte gefiltert sein.

Wenn du die Infos aus dem Log hast, die du benötigst, kannst du mit folgenden Befehlen das Event oben löschen, das Logging deaktivieren und alle Logs löschen.

USE mysql;
SET GLOBAL general_log = 'OFF';
DROP EVENT IF EXISTS delete_some_logs;
RENAME TABLE mysql.general_log TO mysql.general_log_temp;
TRUNCATE TABLE mysql.general_log_temp;
RENAME TABLE mysql.general_log_temp TO mysql.general_log;

Wenn er vorher auch nicht in Verwendung war:

SET GLOBAL event_scheduler = 'OFF';

Anschließend ist alles wieder aufgeräumt und sauber.

Kategorie: Entwicklung

tino-ruge.de wird tino-kuptz.de

Im Laufe des Jahres 2024 wird dieser Blog umziehen. Alle Inhalte werden 1:1 weitergeleitet, nix geht verloren. Neue Domain, alter Autor, alter Inhalt.