Forum: PC-Programmierung [MySQL] Mutex, Locks, große Verständnisprobleme


von Markus (Gast)


Lesenswert?

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

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Du könntest einen Trigger auf Insert/Updates setzen und die 
entsprechende Aktion ggf. zurückweisen.

von Markus (Gast)


Lesenswert?

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 ...

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Ist MySQL unverzichtbar? PostgreSQL hat ein exclusion constraint, das 
möglicherweise in der Lage ist, solche inhaltlichen Beziehungen der rows 
untereinander abzubilden.

http://www.postgresql.org/docs/9.0/interactive/sql-createtable.html#SQL-CREATETABLE-EXCLUDE

von Markus (Gast)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

NB: PostgreSQL kennt sogar geometrische Daten wie Polygone als Datentyp:
http://www.postgresql.org/docs/9.0/interactive/datatype-geometric.html

von der mechatroniker (Gast)


Lesenswert?

mit Transaktionen gehts prinzipiell so (nicht MySQL-Syntax):
1
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
2
3
IF NOT EXISTS (SELECT * FROM tabelle WHERE value1 < @value2 OR value2 > @value1)
4
INSERT tabelle @id, @value1,  @value2
5
ELSE RAISERROR 'Gips schon...'

ist aber deadlock-verdächtig und läuft evtl. während des Insert auch auf 
einen Table-Lock hinaus...

von Markus (Gast)


Lesenswert?

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

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?


von Markus (Gast)


Lesenswert?

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

von Markus (Gast)


Lesenswert?

muahahaha it's alive!!!! ;)
1
CREATE OR REPLACE FUNCTION dsstand_insert_gispolygon() RETURNS TRIGGER AS 
2
$body$
3
  DECLARE
4
    myrec RECORD;
5
  BEGIN
6
    SELECT "ID" INTO myrec FROM "DSSTAND" WHERE Intersects( "GISPOLYGON", NEW."GISPOLYGON") AND "ID" != NEW."ID"  LIMIT 1;
7
    IF FOUND THEN
8
      RAISE EXCEPTION 'POLYGON INTERSECTING!';
9
    ELSE
10
      RETURN NEW;
11
    END IF;
12
  END;
13
$body$ LANGUAGE plpgsql;

Muss ich da noch Table-Locks reinbauen, oder werden die Trigger 
sequenziell abgearbeitet?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.