Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: Suche Alternative zu xact_start in pg_stat_activity

  1. #1
    tigger ist offline Benutzer
    Registriert seit
    02.05.2008
    Beiträge
    41

    Standard Suche Alternative zu xact_start in pg_stat_activity

    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)

    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';
    Und hier ein Funktionsaufruf:
    Code:
    PERFORM sleep_until_prevoise_transacts_are_open(ARRAY['table1'::regclass, 'table2'::regclass], ARRAY['RowShareLock'::varchar, 'ExclusiveLock'::varchar, 'AccessShareLock']);
    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.

    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!

  2. #2
    ads
    ads ist offline Super-Moderator
    Registriert seit
    08.02.2006
    Ort
    MD
    Beiträge
    4.020

    Standard

    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

  3. #3
    tigger ist offline Benutzer
    Registriert seit
    02.05.2008
    Beiträge
    41

    Standard

    Ach so.

    Na gut. Bevor ich den Aufwand betreibe werde ich lieber auf 8.3 upgraden

    Danke schön!

  4. #4
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    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)

  5. #5
    tigger ist offline Benutzer
    Registriert seit
    02.05.2008
    Beiträge
    41

    Standard

    Zitat Zitat von symbiont Beitrag anzeigen
    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
    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!

    Zitat Zitat von symbiont Beitrag anzeigen
    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 ..
    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!

  6. #6
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    Zitat Zitat von tigger Beitrag anzeigen
    Ich pflege ohnehin einen Modifikationszeitstempel.
    ... Zeitstempelmodifikationsspalte etwas größer .. würde hier zur noch mehr Redundanz hervorrufen. Aber trotzdem danke für den Tipp!
    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

    Das Problem bei einem EXCLUSIVE-Lock ist, dass alle danach ankommenden Statements die Tabelle nicht benutzen dürfen.
    "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 ist dann sauber synchronisiert

  7. #7
    castorp ist offline Erfahrener Benutzer
    Registriert seit
    27.06.2009
    Beiträge
    493

    Standard

    Zitat Zitat von symbiont Beitrag anzeigen
    weil wenn die db ausreichend schnell ist du fuer mehrere datensaetze durchaus den selben timestamp erhalten kannst
    Bei einer Auflösung bis auf Mikrosekunden im timestamp Datentyp? Halte ich für seeehr unwahrscheinlich.

  8. #8
    tigger ist offline Benutzer
    Registriert seit
    02.05.2008
    Beiträge
    41

    Standard

    Zitat Zitat von symbiont Beitrag anzeigen
    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
    Wie recht du hast Das fällt mir gerade auch etwas auf die Füße. Na mal sehen. Da muss ich wohl doch vielleicht noch eine Sequence einbauen.

    Zitat Zitat von symbiont Beitrag anzeigen
    "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 ist dann sauber synchronisiert
    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.

  9. #9
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    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)

  10. #10
    symbiont ist offline Erfahrener Benutzer
    Registriert seit
    17.03.2008
    Ort
    NULL
    Beiträge
    1.320

    Standard

    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"

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Links: Tobias Bauer - IT- und Funkdienstleistungen   -   Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen   -   Funkforum