Probleme mit DELETE

Probleme mit DELETE

am 17.12.2006 12:42:13 von Atlan

Hi,

ich habe ein Problem mit DELETE-Anweisungen.

Das Problem ist folgendes:

Ich habe eine Datenbanktabelle, in der Ereignisse hinterlegt sind. Bei
Fälligkeit sollen diese dann verarbeitet werden. Die Pruefung erfolgt
sekundengenau ueber einen Thread (aktives Warten). Nach der Verarbeitung
wird der Eintrag in meiner Ereignisliste geloescht. Ich musste jedoch
feststellen, das bei den naechsten 1 bis 2 Select Abfragen auf diese Tabelle
die eigentlich schon geloeschten Datensaetze immer noch enthalten sind, und
meine Events somit fatalerweise mehrfach verarbeitet werden, was nicht
passieren darf.

Eine FLUSH table [name] Anweisung nach der DELETE Anweisung, fuehrte nicht
zu dem von mir erhofften.

Ich habe das ganze zwar nun mittels einer Liste in meiner Applikation
abgefangen, in der ich die ID's verarbeiteten Ereignisse festhalte, pruefe
ob schon in dieser Liste vorhanden sind, die Liste in regelmaessigen
Abstaenden aufraeume, aber so ganz gluecklich bin ich mit dieser externen
Loesung nicht.

Wie kann ich nur mit Hilfe der Datenbank sicherstellen, das mir eine
SELECT-Abfrage keine Datensaetze mehr zurueckliefert, die "kurz" vorher
mittels DELETE entfernt wurden. Gibt es ggf. Konfigurationsparameter mit
denen ich ein besseres Ergebnis erzielen kann?

Gruss Atlan

Re: Probleme mit DELETE

am 17.12.2006 13:15:48 von Axel Schwenke

"Atlan" wrote:
>
> Ich habe eine Datenbanktabelle, in der Ereignisse hinterlegt sind. Bei
> Fälligkeit sollen diese dann verarbeitet werden. Die Pruefung erfolgt
> sekundengenau ueber einen Thread (aktives Warten). Nach der Verarbeitung
> wird der Eintrag in meiner Ereignisliste geloescht. Ich musste jedoch
> feststellen, das bei den naechsten 1 bis 2 Select Abfragen auf diese Tabelle
> die eigentlich schon geloeschten Datensaetze immer noch enthalten sind, und
> meine Events somit fatalerweise mehrfach verarbeitet werden, was nicht
> passieren darf.

Was *genau* tust du da? Ist das nur ein Thread, der auf die Datenbank
zugreift, oder mehrere? Benutzt du Transaktionen? Und wenn ja, welches
Isolation-Level? Bitte SHOW CREAE TABLE und deine Queries nachreichen!

Aber mit an Sicherheit grenzender Wahrscheinlichkeit trifft MySQL keine
Schuld an deinem Problem.

> Wie kann ich nur mit Hilfe der Datenbank sicherstellen, das mir eine
> SELECT-Abfrage keine Datensaetze mehr zurueckliefert, die "kurz" vorher
> mittels DELETE entfernt wurden.

So lange das der gleiche Thread (die gleiche MySQL-Verbindung) ist,
*kann* das gar nicht passieren. Bei mehreren Threads muß man größere
Geschütze auffahren. In Verbindung mit Datenbanken heißt das i.d.R.
Transaktionen - bei MySQL also InnoDB-Tabellen und Abschied von
AUTO-COMMIT.

Man kann das allerdings auch anders race-condition-frei bekommen,
z.B. indem man in der Event-Tabelle eine Spalte für den Bearbeiter-
Thread vorsieht. Die wird beim Erzeugen des Events auf NULL gesetzt
und wenn ein Thread ein Event bearbeiten will, auf dessen Thread-ID.
Das ganze natürlich mit einer atomaren Operation:

UPDATE events
SET owner_thread =
WHERE scheduled_time <= NOW()
AND owner_thread IS NULL
LIMIT 1

Falls das affected_rows = 1 ergeben hat, hat unser Thread jetzt ein
Ereignis für sich reserviert und kann sich Details holen:

SELECT ...
FROM events
WHERE owner_thread =

Wenn er fertig ist, löscht er das Event:

DELETE FROM events WHERE owner_thread =


XL