TS: Konkurrierender Betrieb beim SELECT->EDIT -> UPDATE

Hallo und guten Tag,

ich möchte den konkurrierenden Betrieb beim SELECT -> EDIT -> UPDATE besser abfangen.

Ein Datensatz wird per HTTP aus der Datenbank gelesen (SELECT) und auf dem Client zum Ändern (EDIT) angezeigt. Nach einer gewissen Zeit wird versucht, den veränderten Datensatz zurückzuschreiben.

Um die Race-Condition abzufangen, verwende ich bisher einen "Conflict-Counter", der bei jedem Update um 1 erhöht wird. Passt der alte Counter nicht zu dem abgefragten in den Client-Daten, meckert der Update-Trigger.

Da aber zwischen SELECT und UPDATE eine relevante Bearbeitungsdauer liegt, würde ich dem benachteiligten Editor gerne frühzeitig eine Nachricht geben, dass die Daten eben von einem schnelleren zurückgeschrieben wurden. Er kann sich dann die weitere Bearbeitung sparen und muss vorher neu lesen.

Noch besser wäre es, wenn man das per rpc.statd regeln könnte, also den Satz solange sperren könnte, wie er zur Bearbeitung ansteht. Nur da geht HTTP nicht mehr... Wie funktioniert das mit Websockets?

Wie sollte ich das am besten machen?

Grüße
TS

--
es wachse der Freifunk
http://freifunk-oberharz.de
  1. Hallo TS,

    Um die Race-Condition abzufangen, verwende ich bisher einen "Conflict-Counter", der bei jedem Update um 1 erhöht wird. Passt der alte Counter nicht zu dem abgefragten in den Client-Daten, meckert der Update-Trigger.

    Das nennt sich „optimistic locking.“

    Wie sollte ich das am besten machen?

    Ich habe das bei unserer internen Applikation so gelöst, dass ein Datensatz via locked TIMESTAMP WITHOUT TIME ZONE solange gesperrt ist, wie der Browser des Editors den Datensatz offen hat. Dazu wird alle 10 Sekunden via Websocket ein Event an den Server gereicht, der das Lock erneuert. Gleichzeitig läuft alle 30 Sekunden ein Cleanup-Job, der stale locks (Locks, die länger als 30 Sekunden nicht erneuert wurden) entfernt (locked wird wieder auf NULL gesetzt).

    Wie du in deiner Umgebung mit Websockets arbeiten kannst, kann ich dir nicht sagen: ich kenne deine Umgebung nicht. Bei mir ist das ein Application Server, der die Websocket-Verbindungen behandelt.

    LG,
    CK

    1. Hallo CK,

      Um die Race-Condition abzufangen, verwende ich bisher einen "Conflict-Counter", der bei jedem Update um 1 erhöht wird. Passt der alte Counter nicht zu dem abgefragten in den Client-Daten, meckert der Update-Trigger.

      Das nennt sich „optimistic locking.“

      Wie sollte ich das am besten machen?

      Ich habe das bei unserer internen Applikation so gelöst, dass ein Datensatz via locked TIMESTAMP WITHOUT TIME ZONE solange gesperrt ist, wie der Browser des Editors den Datensatz offen hat. Dazu wird alle 10 Sekunden via Websocket ein Event an den Server gereicht, der das Lock erneuert. Gleichzeitig läuft alle 30 Sekunden ein Cleanup-Job, der stale locks (Locks, die länger als 30 Sekunden nicht erneuert wurden) entfernt (locked wird wieder auf NULL gesetzt).

      So weit war ich ja auch schon. Das ganze System wird dann recht komplex, da man dann in nahzu jeder Abfrage die Flags in den Datensätzen berücksichtigen muss. Es sollte auch sichergestellt sein, dass ein User nicht länger als xx Minuten einen Satz sperrt.

      Sinnvoller fände ich es daher, ihm beim Update durch jemand anders eine Nachricht schicken zu können.

      Wie wird das hier im Forum mit dem Hinweis gemacht, dass es Veränderungen gab. Wir der auch auf Client-Poll ausgeliefert, oder ist das Server-Push?

      Grüße
      TS

      --
      es wachse der Freifunk
      http://freifunk-oberharz.de
      1. Hallo TS,

        Das ganze System wird dann recht komplex, [...]

        Locking ist kein einfaches Problem.

        Sinnvoller fände ich es daher, ihm beim Update durch jemand anders eine Nachricht schicken zu können.

        Je nachdem, wie wahrscheinlich konkurrierende Updates sind, werden deine User dich verfluchen.

        Wie wird das hier im Forum mit dem Hinweis gemacht, dass es Veränderungen gab. Wir der auch auf Client-Poll ausgeliefert, oder ist das Server-Push?

        Das läuft über Websocket-Events.

        LG,
        CK

        1. Hallo CK,

          Sinnvoller fände ich es daher, ihm beim Update durch jemand anders eine Nachricht schicken zu können.

          Je nachdem, wie wahrscheinlich konkurrierende Updates sind, werden deine User dich verfluchen.

          Das ist mir klar. Entweder ich blockiere die automatische Verarbeitung von Datensatzlisten, oder ich habe den "nur einmal machen müssen"-Komfort für den einzelnen User (Pessimistic Locking).

          Wie wird das hier im Forum mit dem Hinweis gemacht, dass es Veränderungen gab. Wir der auch auf Client-Poll ausgeliefert, oder ist das Server-Push?

          Das läuft über Websocket-Events.

          Also wäre es vermutlich sinnvoll, beide Verfahren zu mischen.
          Da fehlt mir bei MySQL allerdings die Möglichkeit, per Trigger eine externe Funktion (also eine aus der API) auszulösen, oder gibt es die inzwischen?

          Grüße
          TS

          --
          es wachse der Freifunk
          http://freifunk-oberharz.de