Frage

Ich habe entworfen Datenbank-Tabellen (normalisiert, die auf einem MS-SQL server) und schuf eine eigenständige windows-Frontend für eine Applikation, die von einer Handvoll von Benutzern das hinzufügen und Bearbeiten von Informationen.Wir fügen ein web-interface zu erlauben die Suche über unsere Produktion Bereich zu einem späteren Zeitpunkt.

Ich bin besorgt, dass, wenn zwei Benutzer mit dem Bearbeiten beginnen Sie den gleichen Datensatz dann das Letzte zu Begehen, würde das update der 'Sieger' und wichtige Informationen können verloren gehen.Eine Reihe von Lösungen, die den Sinn kommen, aber ich bin mir nicht sicher, ob ich gehe, um einen größeren Kopfschmerzen.

  1. Nichts tun und hoffen, dass zwei Benutzer sind nie zu Bearbeiten, denselben Datensatz zur gleichen Zeit. - Vielleicht nie geschah, aber was ist, wenn es funktioniert?
  2. Bearbeiten von routine könnte speichern Sie eine Kopie der ursprünglichen Daten sowie die updates und dann vergleichen, wenn der Benutzer die Bearbeitung beendet.Wenn Sie sich unterscheiden, zeigen Sie Benutzer-und comfirm update - Erfordern würde, die zwei Kopien der zu speichernden Daten.
  3. Add Letzte Aktualisierung DATETIME-Spalte und überprüfen Sie es passt, wenn wir update, wenn nicht, dann zeigen sich Unterschiede. - erfordert neue Spalte in jeder der entsprechenden Tabellen.
  4. Erstellen Sie eine Bearbeitungs-Tabelle, die registriert, wenn Nutzer beginnen mit dem Bearbeiten eines Datensatzes überprüft werden und verhindern, dass andere Anwender von der Bearbeitung des gleichen Datensatzes. - würde carful Gedanke des Programmablaufs verhindert deadlocks und Aufzeichnungen immer gesperrt, wenn ein Benutzer stürzt aus dem Programm.

Gibt es bessere Lösungen oder muss ich mich für eins von diesen?

War es hilfreich?

Lösung

Wenn Sie erwarten, dass selten Kollisionen, Optimistische Parallelität ist wahrscheinlich Ihre beste Wette.

Scott Mitchell schrieb ein umfassendes tutorial über die Umsetzung dieses Muster:
Implementieren Von Optimistischer Parallelität

Andere Tipps

Ein klassischer Ansatz ist wie folgt:

  • fügen Sie einen booleschen Feld "gesperrt" zu jedem Tisch.
  • setzen Sie diese standardmäßig auf "false".
  • wenn ein Benutzer beginnt, Bearbeitung, tun Sie dies:

    • sperren Sie die Zeile oder die ganze Tabelle, wenn Sie nicht sperren der Zeile)
    • überprüfen Sie die fahne auf die Zeile, die Sie Bearbeiten möchten
    • wenn das flag wahr ist, dann
      • informieren Sie die Benutzer, dass Sie sich nicht mehr Bearbeiten, die Zeile in dem moment
    • anderes
      • setzen Sie das flag auf true
    • die Sperre lösen

    • wenn der Datensatz gespeichert wird, setzen Sie das flag wieder auf false

WÄHLEN Sie FÜR UPDATE und äquivalente sind gut, vorausgesetzt, Sie halten die sperren für eine mikroskopische Menge der Zeit, aber für eine makroskopische Menge (z.B.der Nutzer hat die Daten geladen werden und hat nicht gedrückt 'speichern' sollten Sie verwenden Sie optimistische Parallelität wie oben.(Was ich immer denke, ist irreführend - es ist eher pessimistisch als "last writer wins", die ist in der Regel die einzige andere alternative in Betracht.)

@ Mark Harrison :SQL Server nicht unterstützt, die syntax (SELECT ... FOR UPDATE).

Die SQL Server-äquivalent ist die SELECT Anweisung Hinweis UPDLOCK.

Finden SQL Server Books Online weitere Informationen.

-erstellen Sie zuerst eingereicht (update-Zeit) zu speichern letztes update record -wenn ein beliebiger Benutzer wählen Sie Datensatz speichern, wählen Sie Zeit aus, vergleichen, wählen Sie zwischen Zeit-und update-Uhrzeit-Feld, wenn( update-Zeit) > (wählen Sie time (Zeit), bedeutet einem anderen Benutzer aktualisieren, die diese Datensatz nach Datensatz auswählen

Eine andere option ist zu überprüfen, ob die Werte in dem Datensatz, den Sie ändern sind immer noch die gleichen, wie Sie waren, als Sie begann:

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(Anzeige der customer_nm-Feld und der Benutzer ändert)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

Sie nicht haben zu fügen Sie eine neue Spalte in Ihrer Tabelle (und halten es up-zu Datum), aber Sie haben zu erstellen Ausführlicher SQL-Anweisungen und pass neue und alt Felder, die gespeicherte Prozedur.

Es hat auch den Vorteil, dass Sie nicht die Verriegelung der Rekorde - weil wir alle wissen, dass die Datensätze werden am Ende bleiben gesperrt, wenn Sie nicht sein sollten...

Die Datenbank wird dies für Sie tun.Blick auf "auswählen ...für update", das speziell für diese Art der Sache.Es wird Ihnen eine Schreibsperre auf die ausgewählten Zeilen, die Sie dann commit oder Rollback.

Mit mir, der beste Weg, ich habe eine Spalte lastupdate (timetamp datatype).wenn die select-und update einfach vergleichen Sie diesen Wert ein weiterer Fortschritt dieser Lösung ist, dass Sie können verwenden Sie diese Spalte, um die Spur der Zeit, die Daten zu ändern.Ich denke, es ist nicht gut, wenn man nur erstellen, colum wie isLock für den check-update.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top