Kalle_B: Satz sperren für Änderung

Hallöle,

meine Datenbank ist MySQL 4.1.9-log

Wenn ein Benutzer eine Adresse zum Ändern aufruft, vergeht eine unbestimmte Zeit, bis er das Formular zurückschickt (Mittagspause, Konferenz, ...).

Wenn ich anderen Benutzern auch erlaube, dieselbe Adresse zu ändern, gibt es natürlich ein heilloses Durcheinander. Der letzte überschreibt die Änderung der anderen.

Nun könnte ich ja einen Sperrvermerk im Datensatz machen (Für User "Kalle" bis 5:30 reserviert).

Das war ein Trick aus uralten DOS- Zeiten. Heute macht man das wahrscheinlich anders? Wie ist das Konzept?

Gruß, Kalle

  1. Hi,

    naja, du fügst ein Feld der Tabelle hinzu, speicherst darin deine Sperrungsdaten. Die Sperrungsdaten werden erzeugt, wenn die "Adresse zum Ändern" aufgerufen wird. Ist das Feld zu dem ZEitpunkt NULL, kann eine Sperrung erfolgen, ansonsten behandelst du den anderen Zustand als Fehlerfall und erweitertst deine Programmlogik entsprechend (Redirect) o.ä.. Wenn dann erfolgreich gespeichert wurde, setzt du das Sperrfeld wieder auf NULL.

    Ciao, Frank

    1. Moin!

      naja, du fügst ein Feld der Tabelle hinzu, speicherst darin deine Sperrungsdaten. Die Sperrungsdaten werden erzeugt, wenn die "Adresse zum Ändern" aufgerufen wird. Ist das Feld zu dem ZEitpunkt NULL, kann eine Sperrung erfolgen, ansonsten behandelst du den anderen Zustand als Fehlerfall und erweitertst deine Programmlogik entsprechend (Redirect) o.ä.. Wenn dann erfolgreich gespeichert wurde, setzt du das Sperrfeld wieder auf NULL.

      Alternativ wird beim Abrufen der Daten aus der Tabelle dieser Originalzustand mit gespeichert und beim erneuten Beschreiben zunächst die Unverändertheit der bisherigen Daten festgestellt.

      Sollte sich die DB in der Zwischenzeit geändert haben, kann man zunächst in einem automatischen Schritt feststellen, ob sich die Änderung auf alle Datenfelder auswirkt, oder nur auf einzelne (z.B. zwischenzeitlich ist nur die Telefonnummer geändert worden), die vom aktuellen Bearbeitungsschritt nicht geändert wurden. In so einem Fall lassen sich beide Änderungen störungsfrei zusammenfassen.

      Oder man fügt einen manuellen Bearbeitungsschritt ein, der den Originalzustand, die Änderungen des aktuellen Benutzers und die zwischenzeitlich eingetretene Änderung in der DB auflistet und eine manuelle Zusammenfügung der Daten verlangt. Sofern der automatisierte Schritt stattfindet (was nicht zwingend die beste Lösung sein muß), wären an diesem Punkt nur Felder betroffen, die von beiden Benutzern parallel und unterschiedlich geändert wurden.

      Allerdings muß man beachten, dass der aktuelle Benutzer nicht unbedingt den Hintergrund der zwischenzeitlichen Bearbeitung kennt und möglicherweise einfach seine Änderung in die Datenbank packt, ohne zu recherchieren, welche Information (seine oder die des zwischenzeitlichen Bearbeiters) denn korrekt ist.

      - Sven Rautenberg

      --
      "Love your nation - respect the others."
  2. Hallöle,

    mmmh, recht umfangreich. Eigentlich hatte ich auf so was einfaches gehofft wie "read_for_update", und die DB kümmert sich.

    Habe ich doch schon irgendwo gehört. Bei Oracle vielleicht?

    Wenn mehrere Tabellen von einer Änderung betroffen sind, kann ich ja ein eigenes Projekt aufmachen ...

    Gruß, Kalle

    1. Moin!

      mmmh, recht umfangreich. Eigentlich hatte ich auf so was einfaches gehofft wie "read_for_update", und die DB kümmert sich.

      Habe ich doch schon irgendwo gehört. Bei Oracle vielleicht?

      Wenn mehrere Tabellen von einer Änderung betroffen sind, kann ich ja ein eigenes Projekt aufmachen ...

      Dein Problem mit dem parallelen Bearbeiten von Datenbankdaten ist identisch zum parallelen Bearbeiten von Quelltexten.

      Für Quelltexte gibt es diverse Versionskontrollsysteme (CVS, Subversion,...), und keines ist "einfach". Alle schlagen sich mit dem Problem herum, dass insbesondere das unterschiedliche Verändern der gleichen Programmzeile zu Konflikten führt, die irgendwie gelöst werden müssen.

      Die Methode des Sperrens der Daten gegen Veränderung durch Dritte hilft im Konfliktfall genausowenig, wie die Methode des Zusammenführens und manuellen Bearbeitens.

      Das Sperren hat das Problem festzustellen, wann die Sperre wieder entfernt werden kann. Wenn der Bearbeiter zwei Stunden Mittagspause macht (oder auch nur fünf Minuten an dem Datensatz sitzt), und während dieser Zeit muß ein anderer Bearbeiter einfach nur die Telefonnummer ändern, weil der Kunde gerade angerufen hat - und kann das nicht, weil der Datensatz gesperrt ist, dann wird ihn die Zurückweisung seiner Daten extrem nerven und von der Arbeit abhalten.

      Das Zusammenführen der Änderungen (Merging) in der Form der Versionskontrollsysteme reduziert diese Konflikte auf die Fälle, in denen tatsächlich das gleiche Datenfeld zweimal in unterschiedlicher Form geändert wurde. Der als zweiter speichernde Bearbeiter hat dann zwar die u.U. schwierige Aufgabe, zu entscheiden, welche Änderung korrekt ist und überlebt, bzw. muß die Änderungen irgendwie zusammenführen (Hintereinanderhängen von zwei Kommentaren wäre ja denkbar), aber er wird solch eine Aktion deutlich seltener durchführen, als durch Sperren behindert werden.

      Alternativ kannst du natürlich auch einfach nur die Sessiondauer begrenzen und nach Ablauf einer Zeitperiode das Formular als ungültig zurückweisen - blöd ist dann nur, wenn die Bearbeitung der Daten, Recherche etc., länger gedauert hat, und die Änderungen dadurch verloren gehen würden.

      AJAX kann in diesem Zusammenhang übrigend helfen, das doch sehr starre Konzept des "submit complete form" aufzubrechen. Allerdings nicht ohne Preis: Eventbasiert den Client serverseitig von zwischenzeitlichen Änderungen in der Datenbank zu informieren funktioniert in HTTP natürlich auch mit AJAX noch nicht, es sind daher andauernde Requests zum Server notwendig, die entsprechend Performance kosten und natürlich auch hinreichend abgesichert sein müssen.

      - Sven Rautenberg

      --
      "Love your nation - respect the others."
      1. Moin, Sven,

        danke für deine sehr ausführliche Stellungnahme.

        Ich denke, ich sperre den Satz für eine gewisse Zeit gegen Änderungen weiterer User.

        Das Sperren hat das Problem festzustellen, wann die Sperre wieder entfernt werden kann.

        Entweder nach Uhrzeit oder berechtigter Änderung. Was eher eintritt.

        Wenn der Bearbeiter zwei Stunden Mittagspause macht (oder auch nur fünf Minuten an dem Datensatz sitzt), und während dieser Zeit muß ein anderer Bearbeiter einfach nur die Telefonnummer ändern, weil der Kunde gerade angerufen hat - und kann das nicht, weil der Datensatz gesperrt ist, dann wird ihn die Zurückweisung seiner Daten extrem nerven und von der Arbeit abhalten.

        Na, dann muss er sich ausnahmsweise eine Notiz machen. Es nervt auch, wenn ich Leute anrufen will und da ist besetzt.

        Alternativ kannst du natürlich auch einfach nur die Sessiondauer begrenzen und nach Ablauf einer Zeitperiode das Formular als ungültig zurückweisen - blöd ist dann nur, wenn die Bearbeitung der Daten, Recherche etc., länger gedauert hat, und die Änderungen dadurch verloren gehen würden.

        Deshalb wollte ich ja die Ende- Uhrzeit der Sperrung anzeigen. Habe dann aber wahrscheinlich das Zeitzonenproblem.

        Die Daten werden nach Ablauf der Sperrzeit zwar abgewiesen, aber im Formular angezeigt. Muss dann eben in ein frisches Formular übertragen werden. Das wird der "Schnecke", die soo lange brauchte, dann auch wohl nichts ausmachen ;-)

        AJAX ...

        mal schauen, so langsam arbeite ich mich da ein. Kommt aber eher infrage, um die Liste upzudaten, nachdem ein Eintrag bearbeitet wurde.

        Gruß, Kalle

    2. mmmh, recht umfangreich. Eigentlich hatte ich auf so was einfaches gehofft wie "read_for_update", und die DB kümmert sich.
      Habe ich doch schon irgendwo gehört. Bei Oracle vielleicht?

      Um was soll sich die "DB" kümmern? Um die Konfliktverwaltung? Um das "Sperren" von Datensätzen? Oder einfach um alles?
      ;-)

      Wenn mehrere Tabellen von einer Änderung betroffen sind, kann ich ja ein eigenes Projekt aufmachen ...

      In der Tat, eine reizvolle Aufgabe. Schon mal solche Anforderungen gehabt wie vollständige Historiesierung mit Regelverwaltung für Konflikte?

  3. Huhu Kalle,

    eine einfache Lösung könnte so ausschauen:

    Beim Auslesen der Daten erzeugst Du eine Prüfsumme.
    Diese wird beim Update mitgeschickt.
    Anhand der Anzahl der betroffenen Datensätze (affected rows, 1 oder 0) kannst Du dann
    sagen "ok" oder "Der Datensatz wurde zwischenzeitlich verändert".

    -- Auslesen zum Bearbeiten

    SELECT
     a,b,c,
     MD5(concat_ws('#',id,a,b,c)) as hasherl
    FROM
     TableName
    WHERE
     id=123

    -- Aktualisieren des Datensatzes

    UPDATE
     TableName
    set
     [...]

    WHERE
     id=123
    AND
     MD5(concat_ws('#',id,a,b,c)) = '$hasherl'

    Viele Grüße

    lulu

    --
    bythewaythewebsuxgoofflineandenjoytheday
    1. eine einfache Lösung könnte so ausschauen:

      Beim Auslesen der Daten erzeugst Du eine Prüfsumme.
      Diese wird beim Update mitgeschickt.
      Anhand der Anzahl der betroffenen Datensätze (affected rows, 1 oder 0) kannst Du dann
      sagen "ok" oder "Der Datensatz wurde zwischenzeitlich verändert".

      Na ja, wird der Nutzer, der den Datensatz gerade bearbeitet hat, denn auch happy sein mit der Auskunft, dass die Änderungen "leider nicht übernommen werden konnten."?

      Besser da schon das Auschecken von Datensätzen, von einer Konfliktverwaltung würde ich auch die Finger lassen wollen.

      Statt Prüfsumme also wohl besser Zeitstempel.