# was passiert bei parallelem Datenbankzugriff ?



## ernst (1. Nov 2008)

Hallo allerseits,
zu Demozwecken will ich mit einem Webserver (Apache-Tomcat) durch ein Servlet einen chat realisieren.
Dazu will ich den jeweiligen Text eines Anwenders in einer Datenbank (z.B. Access) speichern und 
den Inhalt dieser Datenbank den anderen Anwendern wieder schicken.
Angenommen es wird gerade in die Datenbank geschrieben und in dem Moment liest ein anderer Anwender
gleichzeitig aus dieser Datenbank. 
Annahme: In der Datenbank steht dieser Text (String):
aaaaaaaaaaaaa-bbbbbbbbbbbbb
Nun soll durch einen Datenbankbefehl dieser String gelesen werden.
Angenommen, es wurden gerade alle a gelesen bis zum Bindestrich.
In diesem Moment wird dann der Lesevorgang unterbrochen (weil ein anderer Anwender etwas in die Datenbank schreiben will) und der andere Anwender schreibt 13 mal ein c.
Steht dann in der Datenbank:
aaaaaaaaaaaaa-ccccccccccccc

Fragen:
1) Kann dieser Fall auftauchen, oder tritt bei einem parallelen gleichzeitigen Zugriff auf dieselbe Datenbank ein Fehler auf (d.h. die Datenbank meldet einen Fehler, d.h. es tritt im Beispiel unten eine Exception auf?

ResultSet rs=null;
String pSQL;
try{
  rs = statementSQL.executeQuery(pSQL);
}
...


2) Wie ist das bei einer Datei?
Wird dort auch eine Exception geworfen?


mfg
Ernst


----------



## Teradil (1. Nov 2008)

Datenbank-Aktionen (Transaktionen) Sind immer "Ganz-oder-gar-nicht"-Vorgänge. Der Lesevorgang wird also komplett zu ende geführt, bevor ein anderer auf dem Datensatz rumschreiben darf.
Für die Synchronisierung solcher Transaktionen ist das Datenbankmanagementsysten zuständig. 

Bei einer Datei ist das anders. Da steht kein DBMS dahinter. Da sollte die Datei dann so lange gesperrt werden, wie jemand darauf zugreift, damit solche "race-conditions" möglichst nicht auftreten können.


----------



## ernst (1. Nov 2008)

> Datenbank-Aktionen (Transaktionen) Sind immer "Ganz-oder-gar-nicht"-Vorgänge. Der Lesevorgang wird also komplett zu ende geführt, bevor ein anderer auf dem Datensatz rumschreiben darf.


Was geschieht, wenn trotzdem ein gleichzeitiger, paralleler Datenbankzugriff versucht wird?
Wird eine Exception geworfen, wie in meinem Beispiel?


> Für die Synchronisierung solcher Transaktionen ist das Datenbankmanagementsysten zuständig.


Was heißt das konkret für die Programmierung?
Was muss ich machen?

mfg
Ernst


----------



## musiKk (1. Nov 2008)

Das heißt eben, dass du nichts machen musst. Es werden keine Exceptions geworfen, weil die Datenbank die parallelen Zugriffe so sortiert, dass nichts passiert. Wenn mehrere gleichzeitig lesen wollen, ist das kein Problem. Wenn aber einer die von jemandem anders zu lesenden Daten modifizieren will, dann kommt immer einer zuerst. Es wird immer eine konsistente Sicht auf die Daten garantiert.
Das Ganze ist auch ein Bestandteil von ACID, nach dem du suchen kannst, wenn dich diese Themen interessieren. Auch die weiterführenden Links in dem Artikel gehören dazu, z. B. das Phantomproblem oder Unrepeatable Read. Das ist ein recht interessantes Thema, das bei mir etwa ein Semester gefüllt hat.


----------



## ernst (1. Nov 2008)

Danke für den Link. Habe etwas gestöbert.
Wenn man z.B. einen Datensatz einfügt, wird dieser Vorgang nicht von einem anderen Einfügevorgang gestört (atomar).
Wie kann ich es aber in Java realsieren, dass z.B. _mehrere_ Datensätze hintereinander eingefügt werden _ohne_von einem anderen parallelen Datenbankzugriff unterbrochen zu werden?
Kann dies nicht zu einem Problem werden, wenn man z.B. 1000000 Datensätze hintereinander einfügen will und dies z.B. 10 Minuten dauert. Wartet dann der andere Datenbankzugriffsversuch so lange?

mfg
Ernst


----------



## musiKk (1. Nov 2008)

Das sollte eigentlich kein Problem darstellen. Auch hier gilt Atomarität. Wenn der Schreiber bei der Hälfte der Datensätze auf einmal ein Rollback macht und damit die bisher eingefügten 500.000 Inserts wieder entfernt, soll das ja keine Auswirkungen auf Leser der Daten haben. Bevor der Schreiber also kein Commit ausführt, dürfte niemand anders die teilweise geschriebenen Daten lesen können und demzufolge sehen die Leser einfach die alten Daten, ohne dass sie erst auf das Ende des großen Inserts warten müssen.

Aber hier wirds glaub ich schon recht datenbank- und konfigurationsspezifisch. Je strenger man auf ACID beharrt, desto mehr wird die Performance beeinflusst. In der Praxis erlaubt man bei sehr großen Datenbanken auch durchaus unsaubere Reads. Ein Beispiel meines Profs: Wenn eine weltweit agierende Bank zu einem bestimmten Zeitpunkt alles Geld, was Kunden bei ihr haben, zählen will, müssten weltweit alle Geldautomaten, alle Überweisungen und sonstige Transaktionen so lange gestoppt werden, bis die Daten gesammelt wurden. Das ist natürlich nicht zumutbar, darum gibt man sich mit ungefähren Werten zufrieden.


----------



## ernst (1. Nov 2008)

> Das sollte eigentlich kein Problem darstellen. Auch hier gilt Atomarität. Wenn der Schreiber bei der Hälfte der Datensätze auf einmal ein Rollback macht und damit die bisher eingefügten 500.000 Inserts wieder entfernt, soll das ja keine Auswirkungen auf Leser der Daten haben. Bevor der Schreiber also kein Commit ausführt, dürfte niemand anders die teilweise geschriebenen Daten lesen können und demzufolge sehen die Leser einfach die alten Daten, ohne dass sie erst auf das Ende des großen Inserts warten müssen.


Wie wird das nicht unterbrochene Einfügen mehrere Datensätze mit Hilfe von Java realisiert?
Die Datenbank kann ja nicht wissen, nach wieviel Datensätze die Atomarität aufhört.
Deshalb muss es bei mehreren Datensätze so etwas geben wie:
Beginn atomar
...
Ende atomar.

Wie wird das in Jaba realisiert (durch welchen Befehl)?

mfg
Ernst


----------



## musiKk (1. Nov 2008)

Naja, das Ende hat man beim Commit. Es kann sein, dass die Datenbank standardmäßig auf autocommit steht, aber das sollte sich mit entsprechenden Parametern bei der Verbindung auch abschalten lassen. Kann sein, dass es auch was mit setSavepoint() des Connection-Objekts zu tun hat, aber da muss ich dann langsam passen (ich vermute allerdings nicht).


----------



## ernst (1. Nov 2008)

Siehe Java ist auch eine Insel im Internet (Transaktionen):
--- Zitat Beginn ---
Transaktionen sind für Datenbanken ein sehr wichtiges Konzept, denn nur so bleibt die Integrität der Daten erhalten. Transaktionen sind mit einer atomaren Ausführung bei Threads vergleichbar, mit dem Unterschied, dass die Datenbank inmitten einer gescheiterten Transaktion die bisher veränderten Werte rückgängig macht.

In der Standardverarbeitung in JDBC wird jede SQL-Anweisung für sich als Transaktion abgearbeitet. Dies nennt sich Auto-Commit. Um jedoch eine Folge von Anweisungen in einer Transaktion auszuführen, muss zunächst das Auto-Commit zurückgesetzt werden. Dann werden die Datenbankmanipulationen ausgeführt, und die Transaktion kann anschließend abgeschlossen (commit) oder zurückgesetzt (rollback) werden.

con.setAutoCommit( false ); 
// Datenbankmanipulationen vornehmen 
con.commit(); 
con.setAutoCommit( true );  // Standard wiederherstellen
--- Zitat Ende ---

mfg
Ernst


----------



## maki (1. Nov 2008)

Lies auch was Fowler dazu zu sagen hat:
http://martinfowler.com/eaaCatalog/optimisticOfflineLock.html
http://martinfowler.com/eaaCatalog/pessimisticOfflineLock.html


----------

