Laden...

Datensätze auf dem Server sperren

Erstellt von Ishildur vor 18 Jahren Letzter Beitrag vor 18 Jahren 3.537 Views
I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 18 Jahren
Datensätze auf dem Server sperren

Ich habe noch eine zweite Frage:
Wie kann ich eigentlich Datensätze auf dem Server sperren.
Wenn also Benutzer (A) einen bestimmen Datensatz am bearbeiten ist, so sollte ihn Benutzer (B) ja nicht gleichzeitig bearbeiten können, sonst überschreiben Sie sich ja gegenseitig die Änderungen ?

I
1.739 Beiträge seit 2005
vor 18 Jahren

Pessimistisches Sperren ist mit Ado.Net nicht möglich(da Zustandslos).
Du kannst auf Ado umsteigen oder optimistisches Sperren über Zeitstempel implementieren.

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 18 Jahren

Pessimistisches / Optimistisches Sperren?
Das sagt mir irgentwie überhaupt nichts...

I
1.739 Beiträge seit 2005
vor 18 Jahren

Pessimistisches Sperren hast du beschrieben.
Ist ein Datensatz in Bearbeitung kann kein anderer ihn bearbeiten. Er ist für die Bearbeitung durch andere Benutzer gesperrt(Zugriff mit Schreibrechten nicht möglich).
Pessimistisches Sperren ist zB. für Reisebüros wichtig. Anzeige der freien Plätze und wenn in Bearbeitung(Kunde in einer Filiale interessiert sich für die Reise, soll das Ding ja in der Zwischenzeit nicht woanders weggebucht werden).

Optimistisches Sperren ist halt optimistisch("wird schon gutgehen") bis zum tatsächlichen Speichern, dann wird überprüft ob der Datensatz zwischenzeitlich verändert wurde(wenn ja wird das Speichern abgewiesen).

Das war nur ne grobe Kurzfassung(es gibt jeweils auch Subtypen).

Für pessimistisches Sperren mit ADO.Net kann man auch Flags in der Tabelle setzen(Gesperrt oder was immer, das erfordert ein zusätzliches Feld in der Tabelle(Wie der TimeStamp für optimistisches Sperren)der TimeStamp würde auch für das Setzen des Flags benötigt, könnte ja inzwischen eine andere Person den DS geclaimt haben). Das Problem ist dabei wieder die Zustandslosigkeit, dh. das Flag sollte über den Zeitstempel in der Programmlogik irgenwann ungültig werden. Ein echtes pessimistisches Sperren ist jedenfalls nicht möglich.

Ich hoffe das hilft dir etwas weiter.

G
205 Beiträge seit 2003
vor 18 Jahren

Mit welcher Datenbank hast du das problem?

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 18 Jahren

Mit dem SQL Server 2005
Ich frage mich, ob es da wirklich keine implementierte Lösung gibt ? 8o Das mit dem zusätzlichen Feld habe ich in MySQL Datenbanken immer so gemacht, nun bin ich schon ein wenig enntäuscht, dass ich dies bei TSQL auch tun muss.

Ich habe noch ein zeites Problem:
Ich will einen Hauptdatensatz und anschliessend einen Detaildatensatz in zwei dafür vorgesehen Tabellen einfügen.

Schritt 1: Datensatz in Haupttabelle einfügen...
Schritt 2: Den neu erzeugten Primärschlüssel auslesen, lastID oder sowas...
Schritt 3: Datensatz in Detailtabelle einfügen mit dem neu erzeugten Primärschlüssel des im vorherigen Schritt eingefügten Datensatz in der Haupttabelle

Problem: Wenn zwischen Schritt 1 und Schritt 2 jemand anderes ebenfalls einen Datensatz in die Haupttabelle einfügt, dann bekomme ich ja den Primärschlüssel dessen Datensatz anstatt desjenigen, welcher ich eingefügt habe. Die Konsequenz ist, dass ich meinen Detaildatensatz dem falschen Hauptdatensatz zuordne.

In MySQL konnte ich das Problem nicht lösen. In Interbase gibt es hierzu die Generators. Der Generator erhöht sich automatisch, nicht der Primärschlüssel. Das Autoincrement passiert also ausserhalb der Tabelle.

Wie löst man das Problem?

4.221 Beiträge seit 2005
vor 18 Jahren

Such mal im SDK nach RowUpdating RowUpdated

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 18 Jahren

Such mal im SDK nach RowUpdating RowUpdated

Was hat denn das mit dem oben beschriebenen Problem zu tun? 🤔

F
10.010 Beiträge seit 2004
vor 18 Jahren

Das mit dem Sperren hat nichts mit dem Sql-Server zu tun, sondern mit der
Zugriffsmethode von ADO.NET.

Es ist von der Philosophie so gedacht, das möglichst wenig Serverlast erzeugt wird,
damit möglichst viele User auf die DB zugreifen können.

Ein sperren von Datensätzen erzeugt eine höhere Serverlast.
Auch das ist so geacht in ADO.NET.

Die Collisionscontrolle soll die Anwendung machen.

Aber das hat nichts mit dem Zu tun, was Du da machen willst.

Das lässt sich natürlich sehr einfach mit einer Transaction beheben.

Connection Öffnen
Connection.BeginTransaction
Insert Ausführen
ID holen
Insert Durchführen
Comit/Rollback durchführen.

4.221 Beiträge seit 2005
vor 18 Jahren

Original von Ishildur

Such mal im SDK nach RowUpdating RowUpdated

Was hat denn das mit dem oben beschriebenen Problem zu tun? 🤔

Lies es dann weisst Du's

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

3.728 Beiträge seit 2005
vor 18 Jahren
Transaktionen

Du musst Transaktionen verwenden, wie FZelle vorgeschlagen hat. Transaktionen können verschiedene Isolationsstufen haben. Mit der Isolationsstufe "Serialisierbar" eliminierst Du sämtliche Problme mit gleichzeitigem Datenzugriff. Allerdings geht das auch etwas zu Lasten der Geschwindigkeit. Du solltest die Dauer Deiner Transaktionen so kurz wie möglich halten. Denn andere Benutzer müssen evtl. warten, bis eine laufende Transaktion abgeschlossen ist.

Eine genaue Beschreibung von Transaktionen und Isolationsstufen findest Du in der Visual Studio Hilfe, in der MSDN (z.B. unter SqlTransaction) oder in der SQL Server Dokumentation.

S
8.746 Beiträge seit 2005
vor 18 Jahren

Ehrlichweise muss man sagen, dass Isolationslevel zu grobschlächtig sind um Objektlocks zu realisieren. Sie eigenen sich herrvorragend um Aktualisiserungsprobleme, z.B. zwischen einem Dateneinfüge- und Datenlese-Prozess zu steuern.

In jedem Fall braucht man geschachtelte Transaktionen. Man kann auch die Select-Anweisungen mit Lock-Statements versehen. Allerdings ist das alles proprietär.

Es bleibt einem natürlich immer noch die Option das Locking mit der Hand zu basteln (lock tables). Vielleicht nichtmal die schlechteste.

G
131 Beiträge seit 2005
vor 18 Jahren

Original von Ishildur

Ich habe noch ein zeites Problem:
Ich will einen Hauptdatensatz und anschliessend einen Detaildatensatz in zwei dafür vorgesehen Tabellen einfügen.

Schritt 1: Datensatz in Haupttabelle einfügen...
Schritt 2: Den neu erzeugten Primärschlüssel auslesen, lastID oder sowas...
Schritt 3: Datensatz in Detailtabelle einfügen mit dem neu erzeugten Primärschlüssel des im vorherigen Schritt eingefügten Datensatz in der Haupttabelle

Problem: Wenn zwischen Schritt 1 und Schritt 2 jemand anderes ebenfalls einen Datensatz in die Haupttabelle einfügt, dann bekomme ich ja den Primärschlüssel dessen Datensatz anstatt desjenigen, welcher ich eingefügt habe. Die Konsequenz ist, dass ich meinen Detaildatensatz dem falschen Hauptdatensatz zuordne.

Wie löst man das Problem?

Das macht Ado.net automatisch. Ich hatte einmal das selbe Problem mit Kundendaten und Adressdaten zu den Kunden. Beide waren in separaten Tabellen. Nun sollte der Kunde und die Adressdaten gleichzeitig in die Datenbank kommen (GUI war ein Dialog). Hilfe habe ich damals im Enwicklerforum von A.Kosch bekommen. Dann noch einwenig das ganze verfeinert und schwups ging es

Link: http://www.dotnet-magazin.de/itr/features/psecom,id,172,nodeid,76.html