Guma: MySql 5 -> Bei UPDATE einen Datenverlust vermeiden

Hallo zusammen,
ich nutze eine PHP-MSQL 5 Updatefunktion für Eintragsänderungen in meiner Datenbank.

Gestern ist folgendes passiert:
Ich haben eine Seite per UPDATE gespeichert und dann war sie verschwunden. Ein Blick in die Datenbank ergab: die ID hat er sich gemerkt, alle anderen felder waren Leer, bis auf die Standardfelder, diese waren wie bei einem neuen Eintrag mit einer 0 versehen.

Jetzt meine Frage: Wie kann sowas passieren und vor allem, wie kann ich dem begegnen, also verhindern, dass der Datensatz beim Speichern ganz ankommt, oder vollständig einträgt. Gibt es da Möglichkeiten. Ich nutze die UPDATE Funktion seit 5 jahren und das ist das erste mal, dass sowas vorkam, trotzdem ärgerlich, denn die Inhalte des Datensatzes waren verschwunden und mussten neu aufgepielt werden.

Grüße Guma

  1. Hi,

    Gestern ist folgendes passiert:
    Ich haben eine Seite per UPDATE gespeichert und dann war sie verschwunden. Ein Blick in die Datenbank ergab: die ID hat er sich gemerkt, alle anderen felder waren Leer, bis auf die Standardfelder, diese waren wie bei einem neuen Eintrag mit einer 0 versehen.

    Dann waren vielleicht die Felder schon in der Query leer, weil dein Script diesen Fehlerfall nicht vernünftig abfängt?

    Jetzt meine Frage: Wie kann sowas passieren und vor allem, wie kann ich dem begegnen, also verhindern, dass der Datensatz beim Speichern ganz ankommt, oder vollständig einträgt.

    Du willst *verhindern*, dass er vollständig eingetragen wird?

    Gibt es da Möglichkeiten.

    Wir kennen dein Script nicht, wissen also auch nicht, wo es unter welchen Umständen ggf. fehlerhaft arbeitet, bzw. die Daten nicht ausreichend validiert.

    Ich nutze die UPDATE Funktion seit 5 jahren und das ist das erste mal, dass sowas vorkam, trotzdem ärgerlich, denn die Inhalte des Datensatzes waren verschwunden und mussten neu aufgepielt werden.

    Wenn man mit einer Versionierung arbeitet, statt Datensätze zu überschreiben, kann man in so einem Fall natürlich leicht auf die vorherige Version zurückgehen.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Hallo und danke ChrisB,

      evtl. waren die Felder schon in der Query leer, weil mein Script diesen Fehlerfall nicht vernünftig abfängt.

      Wie könnte ich vernünftig den fehler abfangen. Ein Feld, oder zwei Felder auf $inhalt != ""; prüfen und nur das Update zulassen, falls Inhalte vorhanden? Oder gibts da was Geeineteres?

      Du willst *verhindern*, dass er vollständig eingetragen wird?

      ups schreibfehler!

      Mit einer Versionierung arbeiten, statt Datensätze zu überschreiben werde ich mir genauer anschauen und vornehmen.

      Grüße Guma

      1. Hi!

        Versuch bitte beim Zitatkürzen, dass die Zitatzeichenanzahl hinterher noch stimmt.

        evtl. waren die Felder schon in der Query leer, weil mein Script diesen Fehlerfall nicht vernünftig abfängt.
        Wie könnte ich vernünftig den fehler abfangen. Ein Feld, oder zwei Felder auf $inhalt != ""; prüfen und nur das Update zulassen, falls Inhalte vorhanden? Oder gibts da was Geeineteres?

        Zunächst solltest du die Ursache ermitteln. Irgendwelche Maßnahmen zu suchen, von denen du nicht weißt, ob sie die Ursache wirksam treffen oder nur dein Testszenario erfolgreich überstehen, in der freien Wildbahn dann aber wieder zu Verlust führen, ist nicht wirklich hilfreich.

        Wenn deine Anwendung zulässt, dass der Client ungestraft Leerfelder schicken darf, obwohl das die Aufgabenstellung nicht gestattet, und du diesen Fall nicht abfängst, dann ... selbst dran schuld.

        Ansonsten würde ich die SQL-Statements loggen. Einfach so nachzustellen wirst du den Fehler nicht können, oder? Deshalb ist wichtig, was tatsächlich passiert ist festzuhalten. Auch der Weg dahin ist interessant. Wie sehen die Variableninhalte an strategisch wichtigen Stellen des Programmablaufs aus? Die solltest du loggen oder bei Nachstellbarkeit durch Kontrollausgaben überprüfen.

        Mit einer Versionierung arbeiten, statt Datensätze zu überschreiben werde ich mir genauer anschauen und vornehmen.

        Das muss dann auch von der Aufgabenstellung her sinnvoll sein. Denn das bedeutet auch Mehraufwand beim Auswerten, sollen nur die aktuellen und nicht alle Historiendatensätze berücksichtigt werden. Versionierung würde ich nicht als Fehlerbekämpfung einsetzen sondern, wenn es tatsächlich benötigt wird. Fehler kann man mit geeigneten Backups ungeschehen machen.

        Lo!

        1. Hallo,

          ergänzend:

          Ansonsten würde ich die SQL-Statements loggen. Einfach so nachzustellen wirst du den Fehler nicht können, oder? Deshalb ist wichtig, was tatsächlich passiert ist festzuhalten. Auch der Weg dahin ist interessant. Wie sehen die Variableninhalte an strategisch wichtigen Stellen des Programmablaufs aus?

          ... und wie sieht die Funktion aus, die aus den Variableninhalten das SQL-Statement erzeugt. Ich könnte mir gut vorstellen, dass wie so oft der Kontextwechsel nicht genügend beachtet wird.

          Freundliche Grüße

          Vinzenz

          1. Hi!

            ... und wie sieht die Funktion aus, die aus den Variableninhalten das SQL-Statement erzeugt. Ich könnte mir gut vorstellen, dass wie so oft der Kontextwechsel nicht genügend beachtet wird.

            Dann müsste zumindest bei der Problembeschreibung (Update löscht alle Felder im Datensatz) ein syntaktisch einwandfreies Statement entstehen, was bei Quotierfehlern eher selten entsteht. Wenn bei einem

            UPDATE .. SET feld1=irgendwas, feld2=irgendwas, ..., feldn=irgendwas WHERE ...

            ein Fehler bedingt, dass der Teil zwischen feld1 und WHERE fehlt, ohne einen Syntaxfehler zu erzeugen, dann werden die Felder außer feld1 ja nicht geleert sondern unberührt gelassen. Es muss ein Statement entstanden sein, dass anstelle der irgendwasse Leerstrings oder NULLs einsetzt, die Feldnamen und das WHERE jedoch in voller Gänze erhält.

            Lo!

            1. Hallo,

              Dann müsste zumindest bei der Problembeschreibung (Update löscht alle Felder im Datensatz) ein syntaktisch einwandfreies Statement entstehen, was bei Quotierfehlern eher selten entsteht. Wenn bei einem

              UPDATE .. SET feld1=irgendwas, feld2=irgendwas, ..., feldn=irgendwas WHERE ...

              ein Fehler bedingt, dass der Teil zwischen feld1 und WHERE fehlt, ohne einen Syntaxfehler zu erzeugen, dann werden die Felder außer feld1 ja nicht geleert sondern unberührt gelassen. Es muss ein Statement entstanden sein, dass anstelle der irgendwasse Leerstrings oder NULLs einsetzt, die Feldnamen und das WHERE jedoch in voller Gänze erhält.

              stimmt. Nicht unmöglich, aber extrem unwahrscheinlich :-)
              Trotzdem interessiert es mich, wie das Statement zusammengesetzt wird.

              Freundliche Grüße

              Vinzenz

              1. ... Danke für alle antworten, die Fehlerquelle ist gefunden:

                Bei Klick auf die Taste Back. springt der Browser zurück und überschreibt ohne die Formulareingaben.

                Lösung: Ich muss also nur prüfen, ob 2 Variablen verfügbar sind und nur dann das UPDATE-query zulassen.

                Prima, dass ihr mir geholfen habt, ich bin sehr dankbar dafür.
                Guma

                1. Hi,

                  Bei Klick auf die Taste Back. springt der Browser zurück und überschreibt ohne die Formulareingaben.

                  Lösung: Ich muss also nur prüfen, ob 2 Variablen verfügbar sind und nur dann das UPDATE-query zulassen.

                  Du hast 5 Jahre mit UPDATE gearbeitet und nie den Inhalt der Variablen vorab geprüft, bevor du dein Statement zusammengebaut hast? Nie ein Leerformular abgeschickt zum Testen? Wie geht das? Wie macht man das?

                  Ich hoffe, da liegt nicht noch mehr im Argen ala "select * from users where password = $_POST[username] oder solche Sachen.

  2. Hello,

    *grins* (überhaupt nicht böse gemeint, sondern vielleicth endlich mal Einer, der das Problem offenlegen würde, wenn ich ihn lieb drum bitte :-))

    Das liest sich nämlich wie ein Nebenläufigkeitsproblem. Vermutlich bedienst Du die Datenbank über eine PHP-API und über HTTP?

    Wird in diesem Interface berücksichtigt, dass HTTP vustands- und damit für diesen Fall auch "verbindungslos" arbeitet? Es findet also keine Dauerhafte Connnection des Clients mit dem Server statt, über die auch ein Locking betrieben werden könnte.

    Deshalb müssten, sollte meine Vermutung hier zutreffen, Maßnahmen getroffen werden, die ein paralleles datenveränderndes Arbeiten auf einem Datensatz kontrollieren können.

    Das sind konstruktive Maßnahemn, die i.d.R. auf das Satzdesign Einfluss haben und am besten auch auf die Zugriffsrechte. Am besten baut man sich Stored Procedures für diesen Einsatz, die dann automatisch einen Konfliktzähler (Schreibzähler) mitführen und kontrollieren. Und man verbietet den direkten (datenverändernden) Zugriff per Update auf die Tabellen.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de