Hallo,
ich habe testweise eine PostgreSQL-DB in der Version 8.3 am laufen und habe dort eine wundervolle Funktion geschrieben um Race-Conditions zu vermeiden.
D.h. wenn ich ein Statement ausführe, will ich danach now() speichern, um beim nächsten Aufruf nur alle Werte bearbeiten zu müssen, die nach diesem Zeitstempel hinzugekommen sind.
Das Problem ist hierbei, dass hierzu alle offenen Transaktionen auf den jeweiligen Tabellen abgeschlossen sein müssen. Ein Lock würde sich in den natürlichen Ablauf der DB einmischen. Darum hier die andere Lösung:
Die folgende Funktion wartet bis alle gezielten Sperren auf bestimmten Tabellen gelöst wurden, um dann ein TRUE zurückzugeben. (Die speziellen Locks werden angegeben, da mich laufende Vacuums nicht interessieren)
Und hier ein Funktionsaufruf:Code:CREATE OR REPLACE FUNCTION public.sleep_until_prevoise_transacts_are_open(my_tables regclass[], my_lock_modes character varying[]) RETURNS boolean AS $BODY$ DECLARE my_open_transact_count integer; BEGIN LOOP SELECT count(*) INTO my_open_transact_count FROM pg_locks JOIN pg_stat_activity ON pg_locks.pid = pg_stat_activity.procpid WHERE relation = ANY (my_tables) AND xact_start < now() AND pg_locks.mode = ANY (my_lock_modes); EXIT WHEN (my_open_transact_count = 0); PERFORM pg_sleep(1); END LOOP; return TRUE; END; $BODY$ LANGUAGE 'plpgsql';
Soweit so gut. Jetzt habe ich das Problem, dass ich diese Funktion auch gern bei meiner PostgreSQL-DB in der Version 8.2 einsetzen würde. Ich musste leider feststellen, dass der View pg_stat_activity dort nicht die Spalte xact_start enthält und auch nicht die darauf verweisende Funktion pg_stat_get_backend_xact_start(s.backendid) besitzt.Code:PERFORM sleep_until_prevoise_transacts_are_open(ARRAY['table1'::regclass, 'table2'::regclass], ARRAY['RowShareLock'::varchar, 'ExclusiveLock'::varchar, 'AccessShareLock']);
Gibt es einen Work-a-round um ein ähnliches Verhalten bei 8.2 zu bekommen. Ich suche also eine Möglichkeit den Zeitstempel für den Transaktionsbeginn zu bekommen.
Vielen Dank!
Imho kommst du da nicht ohne eigene Funktionen - in C geschrieben - heran.
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören
Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler
PostgreSQL Service & Support
Ach so.
Na gut. Bevor ich den Aufwand betreibe werde ich lieber auf 8.3 upgraden
Danke schön!
1. zeitstempel ist doof - nimm lieber ne sequence - die kann man nicht nur fuer ids verwenden .. dann hast du ganz sicher immer eine korrekte erzeugungs-reihenfolge .. wenn du die processing-id auch bei jedem update auf nextval setzt hast du halt die aenderungs-reihenfolge
2. wenn du auf das ende aller anderen tx warten willst - warum forderst du nicht einfach einen exclusive lock an? die funktion kannst du dir sparen auch den unfug mit der lock-tabelle ..
SELECT ... FOR UPDATE ..
Geändert von symbiont (23.11.2009 um 20:09 Uhr)
Ich pflege ohnehin einen Modifikationszeitstempel. Darum denke ich würde hier vielleicht eine Serial nur Redundanz reinbringen. Vielleicht wäre ein Integer ein Performancevorteil, aber die interne Darstellung eines Zeitstempels wird wohl nicht soweit vom Integer entfernt sein. Zusätzlich sind die Statistiken für andere Queries auf der Zeitstempelmodifikationsspalte etwas größer gewählt, um den Planner mit seinen Histogrammen besseres Verhalten zu vermitteln.
Die Statistiken für die Serialspalte würde hier zur noch mehr Redundanz hervorrufen. Aber trotzdem danke für den Tipp!
Das Problem bei einem EXCLUSIVE-Lock ist, dass alle danach ankommenden Statements die Tabelle nicht benutzen dürfen. Genau das soll nicht passieren. Für die Datenbank muss mein warten unspürbar bleiben. Also auch für Updates.
Ich hab darüber schon viel nachgedacht, doch mir erscheint es als die einzige Möglichkeit. Ab 8.3 funktioniert das auch wunderbar!
ich wuerde den timestamp (sofern nicht anders noetig) ganz weglassen - weil wenn die db ausreichend schnell ist du fuer mehrere datensaetze durchaus den selben timestamp erhalten kannst -> das wolln wa nicht
"nachkommende Statements" koennen die tabelle erst wieder nutzen, wenn die exclusive operation abgeschlossen ist .. diese situation entspricht der vorherigen situation .. da ist doch alles in ordnung? genau das wollen wir ja.Das Problem bei einem EXCLUSIVE-Lock ist, dass alle danach ankommenden Statements die Tabelle nicht benutzen dürfen.
das ist dann sauber synchronisiert
Wie recht du hastDas fällt mir gerade auch etwas auf die Füße. Na mal sehen. Da muss ich wohl doch vielleicht noch eine Sequence einbauen.
Im Prinzip hast du recht, aber in die Datenbank schreiben Programme die ihre Daten sofort loswerden wollen. Müssten die jetzt warten bis ich meinen Lock wieder gelöst habe, dann wäre das eher schlecht für die Gesamtperformanz.
also irgendwas in deinem gesamtsystem MUSS warten .. du kannst nicht einerseits synchronisieren wollen aber dann auch wieder nicht ..
wenn deine clients ihre daten loswerden koennen sollen, dann musst du dir aber im klaren sein, dass diese operation asynchron ist und diese clients nichts direkt ueber den erfolg ihrer schreiboperation erfahren ..
dazu koenntest du die einzufuegenden daten an eine queue im client uebergeben (separater thread) welcher dann die daten einfach inserted .. was halt ebenso einfach passiert sobald der lock frei wird ...
das hat insgesamt sogar den vorteil, dass das einstellen in die queue weeeeeeesentlich schneller sein wird, als das unblockierte inserten in die db. .. das dingens wo immer die daten herkommen wird somit eigentlich nie wirklich auf die db warten - es sei denn die queue ist voll .. was bei ausreichend dimensionierter umgebung selten bis garnicht passieren wird.
Geändert von symbiont (23.11.2009 um 23:47 Uhr)
das ziel ist maximale performance .. da halte ich das seeeehhr wahrscheinlich
Code:create table tstest( tstest timestamp without time zone default now() ); insert into tstest values (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT) select * ... "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551" "2009-11-23 22:41:37.551"
Links: Tobias Bauer - IT- und Funkdienstleistungen - Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen - Funkforum
Lesezeichen