2017-02-17 4 views
1

Ich habe einige Client-Code bekam die einige Daten über einige Tabellen, in einfachen Worten, wie so begeht:Wie bekomme ich sofort den Zeitstempelwert nach dem Update?

  • Client [Id, Gleichgewicht, Timestamp]
  • ClientAssets [Id, AssetID, Quantity]
  • ClientLog [Id, ClientId, BalanceBefore, BalanceAfter]

Wenn der Kunde ein Asset kauft, kann ich die folgende Pseudo-Code:

BEGI N TRANSACTION

  1. GetClientRow Wo ID = 1
  2. Hat genug Balance für neue Asset-Kosten? Ja ...
  3. Einfügen in ClientAssets ...
  4. UpdateClient -> UPDATE-Client SET-Kontostand = f_SumAssetsForClient (1) WHERE ID = 1 und Timestamp = TS Von Schritt 1;
  5. GetClientRow Wo ID = 1
  6. INSERT INTO ClientLog BalanceBefore = Balance bei Schritt 1, BalanceAfter = Balance bei Schritt 5.

Am 4. Schritt COMMIT wird die Client-Reihe in 1 Update-Anweisung aktualisiert mit eine Funktion 'f_SumAssetsForClient', die nur die Assets für den Client summiert und den Saldo dieser Assets zurückgibt. Auch in Schritt 4 wird der Zeitstempel automatisch aktualisiert.

Mein Problem ist, wenn ich GetClientRow wieder auf Schritt 5 aufrufen, könnte jemand die Kundenbilanz aktualisiert haben, also wenn ich gehe, um das Protokoll in Schritt 6 zu schreiben, ist es nicht wirklich das Gleichgewicht nach diesen Schritten. Es wäre der Saldo nach einem anderen Schreiben außerhalb dieser Transaktion.

Wenn ich den neu aktualisierten Timestamp aus der Client-Zeile abrufen könnte, wenn ich UPDATE in Schritt 4 aufrufen, könnte ich übergeben, um nur die Client-Zeile zu greifen, wo der TS = der neue aktualisierte TS. Ist das überhaupt möglich? Oder ist mein Design fehlerhaft? Ich sehe keinen Ausweg aus dem Problem der veralteten Daten zwischen den Schritten 5 und 6. Ich habe das Gefühl, dass es ein Problem im Tabellenentwurf gibt, aber ich kann es nicht ganz sehen.

+1

klingt wie Sie brauchen einen Schritt 3.5, das ist "SELECT f_SumAssetsForClient (1)" dann speichern Sie diesen Wert, dann die Aktualisierung, dann schreiben Sie das Protokoll mit den Werten - Sie sollten nicht mit dem Zeitstempel überhaupt beschäftigen - oder führen Sie die gesamte Prozedur als gespeicherte proc –

+0

@MichaelCoxon Oh das macht jetzt total Sinn. Grundsätzlich sind die Datenlesevorgänge jederzeit nach Schritt 4 nicht vertrauenswürdig. Aber wenn ich alle Werte vor dem letzten UPDATE erhalte, das durch die Zeitstempelprüfung geschützt ist, die ein Commit oder Rollback bestimmt, und diese zum Erstellen des Berichts verwenden, dann sollte es in Ordnung sein. Vielen Dank :). –

+1

Nun, Sie führen diese Anweisungen innerhalb einer Transaktion, so würde die gängige Art sein, die Sperre in der 1. Select auf eine WRITE-Sperre (scheint eine SELECT ... FOR UPDATE in MySQL) zu sein, die andere Sitzungen verhindert von der Änderung dieser ID. – dnoeth

Antwort

1

Schritt 1 Bedürfnisse SELECT ... FOR UPDATE sein. Alle anderen Daten, die geändert werden müssen, müssen auch "gesperrt" werden FOR UPDATE.

Auf diese Weise kann sich ein anderer Thread nicht einreihen und diese Zeilen ändern. Sie werden sich wahrscheinlich erst nach COMMITted verzögern oder es könnte einen Deadlock geben. So oder so, die Sache, um die Sie sich sorgen, kann nicht passieren. Keine Zeitstempelspiele.

+0

Ja, ich werde meine Antwort ändern müssen, da dies das ist, was ich am Ende benutzt habe und was am richtigsten erscheint. Was meine anfängliche Frage zeigt, ist, dass es sich um eine baum-/graphähnliche Datenstruktur handelt und das SELECT ... FOR UPDATE speziell für den Umgang mit dieser Art von Datenmodell gedacht ist. –

1

von Kommentar

Kopierten

Klingen wie Sie einen Schritt 3.5 benötigen, die SELECT f_SumAssetsForClient(1) dann Speicher ist, den Wert, kann dann das Update, dann das Protokoll mit den Werten schreiben - Sie shouldnt zu tun haben mit dem Zeitstempel überhaupt - oder tun das gesamte Verfahren als eine gespeicherte proc

Verwandte Themen