Hallo Wissende,
ich will jetzt ganz groß in die PL/pgSQL Programmierung einsteigen.
Dabei geht es zunächst um die Erstellung von Triggern. Da ich einsteige, habe ich wenig Ahnung. Da ich wenig Ahnung habe, wird mein Code wohl Fehler produzieren. Um die Fehler zur erkennen, möchte ich diese in eine Tabelle loggen.
Ich möchte also eine allgemeine/universelle Fehlerbehandlung, bei der es zunächst nur darum geht, dass ich erkennen kann, dass und was für ein Fehler aufgetreten ist.
Ich habe mir das so vorgestellt, dass ich in jede Triggerfunktion einen EXCEPTION-Block einbaue und dort bei einem auftretenden Fehler eine Anfügeabfrage an eine Fehlertabelle rufe.
Deshalb meine Frage:
Welche allgemeinen Parameter (und wie) lassen sich bei einem Laufzeitfehler auslesen?
eine Fehlernummer? (in VB6 z.B. err.number)
eine Fehlerbeschreibung? (in VB6 z.B. Err.Description)
Ich glaube, Du kommst einfacher, die Fehler ganz normal in das Log von PostgreSQL wandern zu lassen. Ein TRIGGER läuft als eine Transaktion, wirft diese einen Fehler so wird die TX zurückgerollt. Wird dann schwer, danach was in einer Tabelle zu finden. Die Error-Codes und Fehlermeldungen sind in der Doku von PG beschrieben.
Btw.: falls Deine Sig stimmt, bist Du mit einer sehr alten Version unterwegs, und hast auch seit wohl Jahren keinerlei Updates gemacht.
Hallo,
ich habe deine Antwort leider nicht so ganz verstanden.
Die Logdatei von PG selbst gefällt mir nicht so recht, da es sehr viele für mich nicht relevante Meldungen enthält. Auch ist die Struktur nicht gerade übersichtlich.
Wird dann schwer, danach was in einer Tabelle zu finden.
Ich habe mir das ungefähr so gedacht:
CREATE OR REPLACE FUNCTION fnctrg()
RETURNS trigger AS
$BODY$
DECLARE eAnz Integer;
BEGIN
eAnz = 4/0;
-- eAnz = 100000000 * 100000000;
EXCEPTION
WHEN division_by_zero
THEN insert into errtab (fdatetime,ftext) values (now(),'division_by_zero');
return new;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Nun hätte ich das Ganze halt universell, dh. statt nur
division_by_zero
möchte ich alle Fehler abfangen und loggen.
Zur PG-Version:
Die DB wird von einem Fremdsystem (GIS) genutzt - Never change a running System. Der DB-Server ist vom Internet nicht erreichbar und intern ist die Sicherheit eher unrelevant.
Aber ich werde mich mal mit dem Admin zusammensetzen und es mit einem Update versuchen :-).
Nimm einfach “WHEN OTHERS” anstatt " WHEN division_by_zero"
Das Problem ist aber, dass das INSERT in die errtab Tabelle in der gleichen Transaktion läuft wie das Statement welches den Fehler verursacht hat. Und da das aber ein rollback erzwingt, wird auch das loggen der Fehlermeldung zurückgerollt.
In Oracle würde man das Problem mit einer “Logging Prozedur” und einer autonomen Transaktionen lösen. Leider unterstützt Postgres das (noch) nicht, deswegen musst Du eine autonome Transaktion simulieren indem Du den INSERT in die errlog Tabelle via DBLink machst: https://www.postgresql.org/docs/current/static/dblink.html
Und da das aber ein rollback erzwingt, wird auch das loggen der Fehlermeldung zurückgerollt.
Bist du dir sicher !? Die Fehlerbehandlung sollte doch den Fehler abfangen und damit ein rollback verhindern.
Nimm einfach “WHEN OTHERS” anstatt " WHEN division_by_zero"
Ja das schon, aber wie kann ich dann die Fehlerart/Fehlermeldung ermitteln, um diese zu loggen? [edit]gefunden SQLERRM[/edit]
Und da das aber ein rollback erzwingt, wird auch das loggen der Fehlermeldung zurückgerollt.
Ich kann das in meinem Fall nicht bestätigen.
Innerhalb meiner Triggerfunktion arbeitet dieser Code so wie ich es wünsche:
CREATE OR REPLACE FUNCTION meintrigger()
RETURNS trigger AS
$BODY$
BEGIN
--- ganz viel schlauer Code
return new;
EXCEPTION
WHEN OTHERS
THEN insert into errtab (fdatetime,ftext) values (now(),SQLERRM);
return new;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
Was mir jetzt halt noch fehlen würde wäre der variable Funktionsname und eine Fehlerzeilennummer.
@akretschmer:
Unabhängig von PG sagt mir meine Erfahrung, dass mit jedem beseitigten Fehler 2 neue auftreten und jedes Update das Programm langsamer macht .
Aber im Ernst, ein System was 2 Jahr zuverlässig gelaufen ist, läuft aller Wahrscheinlichkeit nach auch weitere 2 Jahre sauber, solange sich die Umgebungsbedingungen nicht ändern.
Für mich stellt jedes update zunächst erst mal ein Risiko dar.
Hallo,
also das funktioniert so wie beschrieben alles recht zuverlässig.
Die Anfügeabfrage an die Fehlertabelle wird in jedem Fall ausgelöst, dh. sie ist von einem Rollback nicht betroffen. Ich gehe davon aus, dass zuerst ein Rollback durchgeführt und dann die Fehlerbehandlung (die Aktionen nach dem EXCEPTION) gestartet wird.
Das scheint mir eigentlich auch logisch wenn ich es z.B. mit VB vergleiche:
Wird ein Fehler nicht behandelt -> Programmabsturz. Wird ein Fehler behandelt wird nur die aktuelle Aktion abgebrochen und mit der Fehlerbehandlung fortgefahren
Was mir jetzt noch fehlt sind ein paar mehre Fehlerhinweise zum Mitloggen. So z.B. die auslösende Zeilennummer im Code. Notfalls müsste ich halt ein paar Marker setzen und loggen.