PDA

View Full Version : sql commit und servicepgm



mk
23-10-18, 09:29
Hallo ,

ich habe folgendes Szenario:

RPG Programm läuft mit set option commit=*chg und actgrp(*new).
In dem RPG wird mit Servicemodulen gearbeitet. Es sind keine lokalen Tabellen im RPG.

In dem RPG wird ein Service mit actgrp caller aufgerufen der die DB Operationen ausführt.

//DS an Update Service übergeben
Errorcheck = NEWSA01_updateDataTab01P(DSBildschirmfelder);

if Errorcheck.Errorcode = '0000';
EXEC SQL COMMIT;
return *on; // hier ist SQLSTATE = '00000'
else;
EXEC SQL Rollback;
return *off;
ENDIF;


Das Serviceprogramm läuft mit dem set commit=*none.
Der commit wird einfach ignoriert.

Frage: Wie kann ich in der Konstellation eine Transaktionsteuerung durchführen?
( Wie kann man das Thema Transaktionsteuerung in Servicemodulen lösen )


Gruß
Michael

Fuerchau
23-10-18, 09:41
Grundsätzlich hat jede ACTGRP seine eigene Commit-Definition.
Nun kommt es auf die Aufgabenstellung an:
Ein Service-Programm sollte nie die Transaktion des Aufrufers zerstören, da sonst commit/rollback durchgeführt werden, die der Rufer nicht erwartet.
Muss ein Service-Programm eine eigene Transaktion durchführen, die unabhängig vom Rufer ist, so bietet sich hier eine benannte ACTGRP oder *NEW (was schlechter, also weniger performant, ist) an.

Eine Mischung zwischen Service-Funktionen über eine gemeinsame Transaktion als auch einer eigenen Transaktion kann in einem Service-Programm nicht erfolgen.
Dann kannst du das Transaktionskonzept gleich vergessen.

BenderD
23-10-18, 09:44
... du musst das SRVPGM mit COMMIT(*CHG) wandeln, ansonsten ist alles richtig.

D*B

PS: statt Variable errorcode, wäre das senden einer Escape Message und eine monitor group im Aufrufer eleganter.

mk
23-10-18, 12:43
Hi zusammen,

danke für die Info's

man wird immer schlauer :-)
Mit der Variante *CHG im Service werden wir uns anfreunden.

An dieser Stelle nochmal einen herzlichen Dank an alle Forumsteilnehmer.

Gruß
Michael

Fuerchau
23-10-18, 12:59
Trotzdem solltest du dir das mit dem Commit dann auch überlegen, da dieser ja nun mal die gesamte Transaktion abschließt, nicht nur den kleinen Teil des Services.
Insbesonders das Aufheben von Sperren könnte da ein Pproblem werden.

BenderD
23-10-18, 13:36
... Transaktionssteuerung und Modularisierung sind kein Hexenwerk, ein Programm spielt Commit Master und steuert die Transaktion und beinhaltet üblicherweise selber keine Datenbankzugriffe. Die Zugriffe werden von Zugriffsprogrammen (technisch SRVPGM) gemacht, die als Commit Slaves (:= machen kein Commit oder Rollback) agieren.
Treten in den Slaves Probleme auf, entscheidet der Master ob diese Transaktions relevant sind und agiert entsprechend mit Commit oder Rollback. Der Master läuft in einer benamten ACTGRP, die Slaves in *CALLER.
AS400 typisch muss man beim RCLACTGRP aufpassen, der hat den idiotischen Default OPTION(*NORMAL).
Sperren werden Commit typisch bis zum Transaktionsende gehalten, solange man den Anfängerfehler nicht macht, zwischendurch einen EXFMT zu machen passt das so.

D*B

mk
23-10-18, 14:03
... Transaktionssteuerung und Modularisierung sind kein Hexenwerk, ein Programm spielt Commit Master und steuert die Transaktion und beinhaltet üblicherweise selber keine Datenbankzugriffe. Die Zugriffe werden von Zugriffsprogrammen (technisch SRVPGM) gemacht, die als Commit Slaves (:= machen kein Commit oder Rollback) agieren.
Treten in den Slaves Probleme auf, entscheidet der Master ob diese Transaktions relevant sind und agiert entsprechend mit Commit oder Rollback. Der Master läuft in einer benamten ACTGRP, die Slaves in *CALLER.
AS400 typisch muss man beim RCLACTGRP aufpassen, der hat den idiotischen Default OPTION(*NORMAL).
Sperren werden Commit typisch bis zum Transaktionsende gehalten, solange man den Anfängerfehler nicht macht, zwischendurch einen EXFMT zu machen passt das so.

D*B

Hallo nochmal eine kleine Rückfrage:

Würde es da Sinn machen statt actgrp(*new) den Programmnamen als Aktivierungsgruppe zu verwenden ?

Fuerchau
23-10-18, 14:15
Welchen Namen du dir da ausdenkst spielt keine Rolle.
*NEW wird dann gerne verwendet, wenn man sich nicht sicher ist, dass auch alles zu gemacht wird, was aufgerufene Programme mit *CALLER so hinterlassen und das eigene Programm auf jeden Fall neu initialisiert wird. Allerdings würde da ebenso ein *INLR=*ON ja schon reichen.

Wiederum muss man ebenso sehen, ob dieses Programm u.U. wiederum von woanders aufgerufen wird, usw. usf.
Und für Serviceprogramme gilt i.d.R., wie Dieter ja beschreibt, dass diese ja einen Service bereitstellen und u.U. Fehlercodes zurückgeben. Demnach sollten diese niemals Commit/Rollback machen, da ein Service ja immer einen Aufrufer benötigt.

Ein weiteres Problem bei deinem Beispiel ist u.U., dass STRCMTCTL erst bei der Ausführung des 1. SQL's in einer ACTGRP gestartet wird. Die reine Definition per Option dient nur dem Compiler und generiert keinen Code (siehe Spool).

BenderD
23-10-18, 14:35
@ACTGRP: ich bin eher für benamte ACTGRP, das ist beim DSPJOB einfacher zu verstehen. Wenn ich nix besseres weiß, dann nehme ich den Programmnamen, für stateless Functions nehme ich NORECLAIM.
Da ich sowieso alle statefull Variablen in eine DS this packe, lässt sich das mit clear this reinitialisieren (zudem kann man da leicht mehrere Sets von Zuständen vorhalten).

@Start Commit: wann das gestartet wird, ist eigentlich Banane, die Transaktion startet in jedem Fall Commit Controll, falls das noch nicht vorher passiert ist.

@Fehlercodes: Ich halte nix von Fehler Rückgabe per Parameter und bevorzuge senden einer Escape Message, da muss der Aufrufer reagieren, sonst sägt es ihn runter.

D*B