Wie verändert man einen Wert in einer Datenbank, ohne Gefahr da es ein anderer auch tut?

2 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet

Ein "Select" ist kein Checkout, oder sowas. Gleichzeitige Änderungen sind nicht möglich, wenn es mal zu einer solchen Situation kommen würde, gibt es einen DB-Fehler a la "This record has been modified by another user"

An Sonsten sind 2 Änderungen hintereinander ( 2 Update Statements in 2 unterschiedlichen Sessions) kein Problem ( Gleichzeitigkeit gibt es spätestens bei Commits nicht mehr)


ohwehohach  22.03.2023, 16:13
Gleichzeitige Änderungen sind nicht möglich, wenn es mal zu einer solchen Situation kommen würde, gibt es einen DB-Fehler a la "This record has been modified by another user"

Das stimmt so nicht. Es ist in jedem mir bekannten Datenbanksystem sogar mit erhöhtem Aufwand verbunden, solche Isolationen zu programmieren. Normalerweise klappt das nur mit Transaktionen oder Record Locking.

Aber es ist immer ein Problem, wenn Client A und Client B denselben Datensatz abrufen und dann nacheinander Änderungen speichern. Standard ist eben, dass es hier KEINE Fehlermeldungen gibt, sondern dass das zuletzt geschriebene gewinnt.

0
ZaoDaDong  22.03.2023, 16:20
@ohwehohach

Ok, nichts anderes wollte ich beschreiben. Ich bin irgendwie davon ausgegangen, dass ein technischer Fehler verhindert werden soll.

1
ohwehohach  22.03.2023, 16:20
@ohwehohach

Achso, jetzt habe ich, glaube ich, verstanden, was Du meinst. Ein Update ist eine atomare Operation. Der DB-Server führt solche Operationen normalerweise immer nacheinander aus, niemals gleichzeitig. Daher kommt es normalerweise nicht zu der Meldung, von der Du sprichst.

0
Bohne47 
Beitragsersteller
 22.03.2023, 17:01
@ohwehohach

Ok, also: Wenn ich das soweit richtig verstanden habe: Es gibt, wenn 2 mal gleichzeitig ein Datensatz verändert wird, keine Fehlermeldung, sondern eines der beiden "gewinnt" und wird hingeschrieben. Das Problem ist halt: ich möchte einen Besucherzähler einbauen, der die Besucher die einen bestimmten Button geklickt haben in der Datenbank zählt (so ähnlich wie bei diesem was würdest du eher Game online wo man sieht wie viele Leute die Gleiche Antwort wie man selber gewählt haben.) Wie könnte man das beheben?

0
ZaoDaDong  22.03.2023, 17:23
@Bohne47

Fuer jeden besucher ein zeitstempel datensatz in eine tabelle schreiben und die Anzahl per count auswerten. Koennte man visits nennen.

2
Bohne47 
Beitragsersteller
 22.03.2023, 16:07

Also kommt dann ein Fehler und es wird abgebrochen oder versucht es der Computer erneut?

0
ZaoDaDong  22.03.2023, 16:08
@Bohne47

Die Session, die als letztes bzw. vom DB-Server als zweitrangig bestimmt, ihr Update machen wollte, wird einen Fehler erhalten. Dann muss der Datensatz neu selektiert werden und das Update kann erneut versucht werden.

0
ZaoDaDong  22.03.2023, 16:12
@Bohne47

Kommt eben auch drauf an, wie man diese Updates macht. Direkt per SQL auf der Datenbank abgesetzte Update-Statements sollten sich nicht in die Quere kommen, außer vielleicht es sind noch Trigger im Spiel.

0
ZaoDaDong  22.03.2023, 16:17
@Bohne47

Versteh mich nicht falsch, die Daten, die man dann in die DB schreibt, können logisch dennoch nicht korrekt sein, aber gespeichert werden sie ohne technischen Fehler.

0

Dann müsstest Du eine Transaktion mit einem Isolation-Level oder Record Locking verwenden. Aber ja, das ist sogar oftmals ein Problem. Standardmäßig ist es eben nicht so, dass Datenbanken solche Fälle erkennen. Normalerweise gewinnt der, der zuletzt schreibt.

Beispiel:

Client A liest Datensatz A

Client B liest Datensatz A

Client B ändert im Datensatz das Feld "Name" auf Hallo

Client B macht ein Update auf Datensatz A

Client A ändert im Datensatz das Feld "Name" auf Welt

Client A macht ein Update auf Datensatz A

=> In der Datenbank steht im Datensatz A der Wert Welt.

Eine genaue Anleitung, wie man das verhindern kann, gibt es nicht. Im speziellen Fall solcher Increments, wie Du sie ansprichst, gibt es beispielsweise im SQL Server ein UPDATE ... OUTPUT Statement, das den Wert erhöht und den erhöhten Wert dann liefert. Anderenfalls müsste man eben das Update-Statement so schreiben, dass nicht der gelesene Wert + 1 verwendet wird, sondern der aktuelle Wert + 1 (z.B. für "Gelesen"-Zähler). Aber das hängt ganz von der Situation ab.


Bohne47 
Beitragsersteller
 22.03.2023, 17:18

Wie lange braucht es denn wenn z.B. der Wert mit Select ausgelesen, dann um 1 erhöht wird und dann mit update eingefügt wird? Weil wenn das irgendwie 0.5 sekunden dauert ist mir das auch egal für einen besucherzähler, dann stimmt es halt nicht so ganz.

0
ohwehohach  23.03.2023, 08:36
@Bohne47

Musst Du mal messen. Das kann sehr unterschiedlich sein. Normalerweise sollte es schnell gehen.

0
ohwehohach  23.03.2023, 10:21
@Bohne47

Aber wie ZaoDaDong schon schreibt: Besucherlogs würde ich in Form einer Tabelle schreiben und nicht einfach als Zähler. Dann kannst Du den aktuellen Besucherstand mit einem einfach SELECT COUNT(*) ermitteln.

0