Guten Morgen,
ich hab immer noch große Verständnisprobleme mit MySQL und
Nebenläufigkeit.
Abstrahiert ist mein Problem folgendes:
Angenommen ich hab eine Tabelle, die ganz simpel einfach so aussieht:
id (primary, int), value1 (int), value2 (int)
und ich hab User, die über ein Java Servlet Einträge in der DB
hinterlassen können.
Hierbei soll es - vereinfacht - mehrere Regeln geben:
- value1 < value2 (das ist immer gegeben und muss nicht gesondern
berücksichtigt werden)
- Es dürfen keine Überschneidungen von Intervallen [val1;val2] in der
Datenbank existieren. Beispiel:
Wenn zwei User folgendes Eintragen:
val1 = 10, val2 = 100, dann ist das quasi ein Interval [10;100], dann
darf kein User z.B. [5;50] eintragen, aber er dürfte [5;9] eintragen.
Soweit ist das hoffentlich klar. In der Realität handelt es sich um
konvexe Polygone, die sich nicht überschneiden dürfen, aber ich denke,
für die Erklärung ist das verständlich. Wichtig ist - glaub ich
zumindest - dass es von MySQL keine Möglichkeit gibt, das beim Insert zu
überprüfen.
Das Problem hierbei ist jetzt, dass ich im Grunde erstmal nachschauen
muss, ob das Intervall, das eingetragen werden soll, in der Datenbank
existiert und wenn nicht, dann wird es eingetragen. Die Servlets können
aber im Grunde parallel und sogar auf verschiedenen Rechnern
gleichzeitig ausgeführt werden und da gibts dann die bekannten Probleme,
wofür man normalerweise Mutex verwendet.
Es gibt hierzu mehrere Ideen, wie man das Problem lösen kann:
- Die Servlets mit einem Mutex locken - ist aber Gift für die
Skalierbarkeit und funktioniert nicht in z.B. einer Cloud.
- Die Tabelle mit einem MySQL-Lock locken, da besteht aber das Problem,
dass ich zu 99% unnötig die Tabelle locke und andere User, die
Intervalle eintragen wollen, die nicht im Konflikt sind, unnötig
abbremsen würde.
Hat da jemand eine Ahnung, wie sowas funktionieren könnte?
Wäre dankbar für Hilfe ... Das Problem verwirrt mich jetzt schon seit
ein paar Wochen und da muss es doch eine einfache und effiziente Lösung
geben ...
Grüße,
Markus
Mit Triggern hab ich bisher noch nichts gemacht, aber auf den ersten
Blick sehen die Möglichkeiten interessant aus.
Was ich bisher gelesen habe, müsste ich aber dann im Trigger die
Überprüfung der Intervalls, bzw in der echten Anwendung eines Polygons
machen, was wahrscheinlich nicht möglich ist.
In der echten Applikation ist es so, dass ich zusätzlich zum Polygon
auch das Umgebende Rechteck gespeichert habe und so schnell mögliche
Kandidaten finden kann, die man genauer untersuchen muss.
Ich bezweifle, dass es hierfür eine effiziente ähnliche Möglichkeit in
MySQL-Syntax als Trigger gibt ...
Lock wäre sicherlich das einfachste für eine erste Lösung, wenn es
Probleme mit der Skalierbarkeit gibt würde ich auch versuchen die
Überprüfung in einem Trigger zu machen.
Andreas Schwarz schrieb:> Genau dafür wurden Transaktionen erfunden.
Es wäre nett, wenn du das etwas ausführlicher erläutern könntest.
Ich nehm Transaktionen her, um zu gewährleisten, dass meine DB
konsistent bleibt im Fehlerfall, weil ich dann einen Rollback machen
kann.
Ein Zeilen-Lock, wie bei "SELECT ... FOR UPDATE" oder sowas, trifft hier
ja nicht zu, weil eine neue Zeile eingefügt wird, die von allen anderen
Zeilen im Prinzip abhängt. Wüsste also nicht, wie ich da um einen
Table-Lock herumkommen sollte oder wie das mit Transaktionen gehen soll.
Andreas Schwarz schrieb:> Lock wäre sicherlich das einfachste für eine erste Lösung, wenn es> Probleme mit der Skalierbarkeit gibt würde ich auch versuchen die> Überprüfung in einem Trigger zu machen.
Okay, das ist eine gute Aussage. Dann behalte ich das mal im Hinterkopf
und versuchs mit Table Locks.
@A.K.
> Ist MySQL unverzichtbar? PostgreSQL hat ein exclusion constraint, das> möglicherweise in der Lage ist, solche inhaltlichen Beziehungen der rows> untereinander abzubilden.
Interessant, mit PostgreSQL hab ich noch nichts gemacht. Nein, ich bin
nicht an MySQL gebunden - es hatte bisher einfach das gemacht was es
soll.
Ich schau mir die Möglichkeiten von PostgreSQL an und auch wieviel
Arbeit es wäre, mein bestehendes Projekt umzustellen, für den Fall,
PostgreSQL kann wirklich das, was ich brauche.
Danke!
Grüße,
Markus
A. K. schrieb:> NB: PostgreSQL kennt sogar geometrische Daten wie Polygone als Datentyp:> http://www.postgresql.org/docs/9.0/interactive/dat...
Sehr interessant! PostgreSQL hat auch Geometrische Funktionen, mit denen
man direkt testen kann, ob sich z.B. Polygone schneiden.
Dann könnte man wirklich Trigger bauen, die erst die Polygon-Kandidaten
bestimmen und dann nochmal genau schauen, ob sich da was schneidet.
Danke für die Hinweise!
Grüße,
Markus
Mittlerweile hab ich meine DB nach PostgreSQL migriert und das war ein
Haufen Arbeit. Scheint keine guten automatischen Tools zu geben, die die
Constraings für Fremdschlüssel, die Sequenzgeneratoren für
Primärschlüssel oder die Indizes mitübernehmen. Oder sie kosten was ;)
Dann musste ich feststellen, dass der org.postgres.PGpolygon datentyp
zwar von datanucleus supported wird, das aber in einem nutzlosen bytea
in der DB landet und damit nutzlos wird.
Mit PostGIS funktionierts jetzt, aber dann hätte ich auch OpenGIS mit
mysql verwenden können, was Andreas schon angemerkt hat.
Naja, Hat ein paar Tage gekostet, aber es macht jetzt das, was es soll.
Eine letzte Frage vlt ...
Wenn ich einen On-Insert Trigger baue, muss ich innerhalb des Triggers
irgendwas locken? Oder werden die Trigger ausschließlich seriell
ausgeführt?
Grüße,
Markus