Daniel.: Änderungen in DB mitloggen

Hallo liebe Gemeinde,

ich habe auf Basis von php und MySQL ein Verwaltungstool gebaut (viele Formulare für INSERTs, UPDATEs, DELETEs..., Login mit Hilfe von Sessions)
Ich speichere zur Kontrolle und zum Nachweis mit, wer gerade in welchem Datensatz gearbeitet hat (Klaus hat am 29.10.08 14:36 Daten im Formular xy geändert). Was ich aber eigentlich gern haben will, ist eine Art Protokoll über die einzelnen Werte:

29.10.08 15:36 - Klaus - Feld A in Formular X geändert von 100 auf 200
29.10.08 15:40 - Tina - Feld B in Formular Y geändert von "abc" auf "xyz"
...

Bei bspw. einem Update ziehe ich das Update ja über alle Formularfelder, also auch die, die nicht geändert wurden. Und da meine Formulare teilweise > 50 Felder haben, wird das schnell sehr unübersichtlich, so dass ich eigentlich nur die geänderten Werte mitloggen (und vor allem allen Nutzern zur Verfügung stellen)möchte.

Hat jemand eine Idee?

daniel

  1. echo $begrüßung;

    Bei bspw. einem Update ziehe ich das Update ja über alle Formularfelder, also auch die, die nicht geändert wurden. Und da meine Formulare teilweise > 50 Felder haben, wird das schnell sehr unübersichtlich, so dass ich eigentlich nur die geänderten Werte mitloggen (und vor allem allen Nutzern zur Verfügung stellen)möchte.

    Hat jemand eine Idee?

    Ich denke nicht, dass dir was anderes bleibt, als vor dem Update den Datensatz auszulesen, und zwischen diesen und den neuen Werten die Differenz festzustellen. Wenn du das nicht in deiner Anwendung machen willst, mach es in einem Trigger. Dabei besteht aber das Problem, wenn der Name des Users nur eine Größe in deinem Programm ist, ihn im Update-Statement unterzubringen, sonst kennt der Trigger ihn nicht[1]. Anders wäre es wenn nur das DB-Login protokolliert werden soll.

    [1] Eine Spalte LastUpdatedBy mitzuführen kann Abhilfe schaffen.

    echo "$verabschiedung $name";

  2. Hello,

    Du kannst, entsprechende Installtion udn Konfiguration von MySQL vorausgesetzt, ein transaktions-Log führen lassen. Da müsstest Du mal unter "Binary Log" suchen im Manual.

    Dieses Log schreibt alle Änderungen automatisch mit. Das benötigt man, wenn man einen Replikationsdienst einrichten will. Außerdem kann man es natürlich auch zur Kontrolle benutzen.

    Aber wenn Dir nur an einer Absicherung bestimmter Anfragen etwas liegt, dann richte mittels Stored Procedures eine zusätzliche Schicht ein. Clients haben dann keinen direkten Zugriff mehr auf die Tabellen und die Befehle der Datenbank, sondern können nur noch die Procedures ausführen lassen. Diese schreiben dann bei Bedarf auch ein Log.

    Eine vergleichbare Light-Lösung dazu ist das Scripten in PHP oder einener anderen Sprache. Der Client darf nur das PHP-Script ausführen, dieses ruft dann die Abfragen auf und lässt die Logs schreiben. Dabei muss die (Script)sprache nicht an HTTP gebunden sein.

    Liebe Grüße aus Syburg bei Dortmund

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. echo $begrüßung;

      Du kannst, entsprechende Installtion udn Konfiguration von MySQL vorausgesetzt, ein transaktions-Log führen lassen. Da müsstest Du mal unter "Binary Log" suchen im Manual.
      Dieses Log schreibt alle Änderungen automatisch mit. Das benötigt man, wenn man einen Replikationsdienst einrichten will. Außerdem kann man es natürlich auch zur Kontrolle benutzen.

      An MySQLs Logging-Fähigkeiten dachte ich auch zuerst, verwarf den Gedanken aber wieder. Das Binary Log ist nicht dazu gedacht, vom Menschen gelesen zu werden. Dementsprechend sieht es auch aus. Es gibt ein Query-Log, das ist lesbarer, da es eine Textdatei ist. Aber auch das ist nicht das was Daniel will, weil damit wieder das komplette UPDATE-Statement mitgeschrieben wird und nicht nur das Delta.

      echo "$verabschiedung $name";

      1. Hello,

        An MySQLs Logging-Fähigkeiten dachte ich auch zuerst, verwarf den Gedanken aber wieder. Das Binary Log ist nicht dazu gedacht, vom Menschen gelesen zu werden. Dementsprechend sieht es auch aus. Es gibt ein Query-Log, das ist lesbarer, da es eine Textdatei ist. Aber auch das ist nicht das was Daniel will, weil damit wieder das komplette UPDATE-Statement mitgeschrieben wird und nicht nur das Delta.

        Das mit dem kompletten Statement stimmt. Das hält auch mächtig den Verkehr auf, insbesondere bei Updates aus Subselects. So zumindest meine Erinnerung an die eigenen Tests.

        Aus dem Binaray kann man mWn aber mit MySQL-Funktionen die gewünschten Informationen extrahieren. Ich habe im Moment leider keine Zeit, das zu suchen und/oder zu testen. Aber gelesen habe ich das. Und es soll, wenn man sowieso schon das Binaray schreibt wegen der Replikationsfähigkeiten immer noch die schmerzloseste Variante sein.

        Und das mit der Replikation habe ich mal ausprobiert. Das bremst wirklich.

        Liebe Grüße aus Syburg bei Dortmund

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. echo $begrüßung;

          Aus dem Binaray kann man mWn aber mit MySQL-Funktionen die gewünschten Informationen extrahieren. Ich habe im Moment leider keine Zeit, das zu suchen und/oder zu testen. Aber gelesen habe ich das.

          Das Kapitel The Binary Log schweigt sich darüber aus. Es erwähnt nur mysqlbinlog, mit dem man sich das Binary Log ausgeben lassen kann, und damit erhält man auch nur einen Stapel der abgearbeiteten Statements in voller Länge. Also unbrauchbar für Daniel. Wenn man sich mal die Binärlogdateien ansieht steht da auch nicht viel mehr drin als die Statements.

          Und das mit der Replikation habe ich mal ausprobiert. Das bremst wirklich.

          Das Binary Log macht den Server um 1% langsamer, sagt das Handbuch. Replikation ist im Handbuch umständlicher beschrieben als es letztlich aufzusetzen geht. Nach meiner Erfahrung ist das einzige was da bremst das Lesen des Handbuchs vor dem Aufsetzen. Ich betreibe Replikation aber nur aus Redundanzgründen und auch keinen hochbelasteten Server.

          echo "$verabschiedung $name";

          1. Vielen Dank erstmal für diese kompetenten Anworten. Hab mir schon gedacht, dass es eher knifflig wird. Vielleicht muß ich es doch auf Scriptebene versuche.
            Fixe Idee: Ich werde das SELECT-Statement (mit dem ich die Werte ins Formular ziehe) mit ner Menge substring & co. zerhacken oder bspw. in ein Array schieben, das gleiche dann mit dem UPDATE-Statement machen, diese miteinander vergleichen und die Änderungen ausgeben. Meinungen? Bedenken?

            Schöneen Feierabend
            Daniel

            1. Hi,

              Fixe Idee: Ich werde das SELECT-Statement (mit dem ich die Werte ins Formular ziehe) mit ner Menge substring & co. zerhacken oder bspw. in ein Array schieben, das gleiche dann mit dem UPDATE-Statement machen, diese miteinander vergleichen und die Änderungen ausgeben. Meinungen? Bedenken?

              Letzteres.

              Auf Feld-Ebene zu vergleichen, was sich geaendert hat, klingt unkomplizierter.

              MfG ChrisB

              --
              „This is the author's opinion, not necessarily that of Starbucks.“
            2. echo $begrüßung;

              Fixe Idee: Ich werde das SELECT-Statement (mit dem ich die Werte ins Formular ziehe) mit ner Menge substring & co. zerhacken oder bspw. in ein Array schieben, das gleiche dann mit dem UPDATE-Statement machen, diese miteinander vergleichen und die Änderungen ausgeben. Meinungen? Bedenken?

              Nebenläufigkeit. Wenn A die Daten abfragt und auf der Formularseite darstellt, dann eine Weile lang nichts damit machen kann, zwischenzeitlich B die Daten geändert hat, kommst du nun mit deinen veralteten SELECT-Daten und merkst nicht, was A gerade an der B-Änderung unwissentlich rückgängig macht. Zu finden ist diese Änderung in deinen Logs dann jedenfalls nicht. Das ist übrigens nicht nur ein Logging-Problem.

              Und was willst du überhaupt an dem SELECT-_Statement_ stringverarbeiten?

              echo "$verabschiedung $name";

              1. Hallo,

                Und was willst du überhaupt an dem SELECT-_Statement_ stringverarbeiten?

                vermutlich die Werte herausziehen, die er vorher eingebaut hat (und eigentlich noch in irgendwelchen Variablen haben müsste ...).
                Ich plädiere für die von Dir gleich zu Beginn vorgeschlagene Trigger-Lösung.

                Freundliche Grüße

                Vinzenz

            3. Hello,

              Vielen Dank erstmal für diese kompetenten Anworten. Hab mir schon gedacht, dass es eher knifflig wird. Vielleicht muß ich es doch auf Scriptebene versuche.
              Fixe Idee: Ich werde das SELECT-Statement (mit dem ich die Werte ins Formular ziehe) mit ner Menge substring & co. zerhacken oder bspw. in ein Array schieben, das gleiche dann mit dem UPDATE-Statement machen, diese miteinander vergleichen und die Änderungen ausgeben. Meinungen? Bedenken?

              Geht es da nun nur ums Loggen, oder darum, Nebenläufigkeitsprobleme zu vermeiden?

              Die vermeidest Du am besten mit einem Schreibzähler im Datensatz, der bei jeder Veränderung um eins hochgezählt wird. Das kannst Du dann durch einen Trigger besorgen lassen.

              Liebe Grüße aus Syburg bei Dortmund

              Tom vom Berg

              --
              Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de