Wednesday, August 6, 2008

[pgsql-de-allgemein] RE: [pgsql-de-allgemein] In Funktion prüfen ob Zeile existiert

Markus Wanner schrieb:
> > Wenn man die Transaktion in Session A serealisierbar macht
> > (START TRANSACTION ISOLATION LEVEL SERIALIZABLE in Session A),
> > wird der Erfolg auch nicht glücklich machen, dann bekommt die
> > Session A einen Error 40001.
>
> ..was doch ein SERIALIZATION FAILURE, und deshalb absolut korrekt ist an
> der Stelle. Bau auf Seite der Applikation einen retry-loop um die ganze
> Veranstaltung und gut (und performant).

Ja, das ist völlig korrekt.
Ich wollte ja nur erwähnen, daß es noch ein paar andere Dinge zu
bedenken gibt.

Und mit einem nachträglichen Test könnte man auch die
"UPDATE first"-Methode krisensicher machen: Aktion wiederholen,
wenn das INSERT eine primary key violation ergibt.
Auch wenn das vielleicht weniger hübsch ist.

> Im READ COMMITTED mode waere die Alternative noch, mit SELECT .. FOR
> UPDATE zu testen, ob's solch ein Tuple schon gibt. Wenn ja, ein UPDATE
> drauf, wenn nein den INSERT. Weniger performant als SERIALIZABLE
> (pessimistic locking), aber Du sparst Dir damit evtl. den retry-loop in
> der App (zumindest wenn Du auch noch darauf achtest, keine deadlocks zu
> provozieren).

Session A: Session B:

START TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT 1 FROM test WHERE id = 1 FOR UPDATE;

?column?
----------
(0 rows)
START TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT 1 FROM test WHERE id = 1 FOR UPDATE;

?column?
----------
(0 rows)

INSERT INTO test (id, val) VALUES (1, 'Session a');
COMMIT;

INSERT INTO test (id, val) VALUES (1, 'Session b');

ERROR: duplicate key value violates unique constraint "test_pkey"

Liebe Grüße,
Laurenz Albe

--
Sent via pgsql-de-allgemein mailing list (pgsql-de-allgemein@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-de-allgemein

No comments: