Sie sind nun wieder eingeladen, die Diskussion spezieller technischer Probleme mit zu verfolgen. Bitte schicken Sie Fragen, Anregungen oder Antworten zu den vorgestellten Themen – ebenso wie Ihre Kritik – an unsere e-Mail-Adressen: dieter.bender@midrangemagazin.de oder redaktion@midrangemagazin.de

Frage:

Wir haben eine Java-Anwendung, die über JDBC auf eine Datenbank auf unserer AS/400 zugreift. Die Anwendung bedient eine externe Schnittstellendatei mit Daten und lief bisher ohne Probleme. Seit kurzem bricht die Übertragung hin und wieder mit der Fehlermeldung „Connection does not exist“ ab, nachdem sie bereits Sätze übertragen hat.

Antwort:

In diesem Fall können eine Reihe von Ursachen in Frage kommen. Ein Programmfehler scheidet aus, da die Anwendung bisher lief und keine Änderungen vorgenommen wurden. Da bereits Sätze übertragen wurden, muss die Verbindung zur Datenbank ursprünglich bestanden haben. Die oben angeführte Fehlermeldung deutet darauf hin, dass diese Verbindung abgebrochen oder unterbrochen wurde.

Für den Abbruch selber kommen Treiberfehler in Frage. Wenn der Abbruch auf der Client-Seite erfolgt ist, dann sollte aber eigentlich noch eine spezifischere Fehlermeldung zu erwarten sein. Soweit die Verbindung seitens der Datenbank abgebrochen wurde, sind weitere Fehlerhinweise dort zu suchen. Einstiegspunkt zur erweiterten Fehlersuche sind die Jobprotokolle der Datenbank-Serverjobs sowie die Jobeigenschaften des Datenbank-Serverjobs.

Für den so genannten Native-Treiber heißt der Serverjob, der die Connection versorgt, QSQSRVR und wird im Subsystem QSYSWRK ausgeführt. Für den Toolbox-Treiber heißt das entsprechende Pendant QZDASOINIT und wird im Subsystem QUSRWRK ausgeführt.

In beiden Fällen werden diese Jobs über vorgestartete Jobeinträge der Subsystem-Beschreibungen gestartet und unter dem Benutzer QUSER ausgeführt. Für jede angeforderte Connection wird nun mit einem bereits laufenden Job aus einem entsprechenden Pool verbunden und auf das Benutzerprofil der Verbindung auf den anfordernden Benutzer gewechselt.

Die Eigenschaften der Serverjobs werden durch Einstellungen des AS/400-Workmanagements festgelegt. Für die vorgestarteten Jobeinträge muss man dazu die Subsystembeschreibungen heranziehen (DSPSBSD).

Subsystembeschreibung anzeigen

System: ADA
Subsystembeschreibung: QUSRWRK Bibliothek: QSYS
Status: ACTIVE

Auswahlmöglichkeiten:

1. Verarbeitungsattribute
2. Pool-Definitionen
3. Autostartjob-Einträge
4. Datenstationseinträge (Name)
5. Datenstationseinträge (Art)
6. Jobwarteschlangen-Einträge
7. Leitwegeinträge
8. DFV-Einträge
9. Einträge für ferne Standorte
10. Vorgestartete Jobeinträge

Weitere …
Auswahl oder Befehl
===> 10

F3=Verlassen F4=Bedienerführung F9=Auffinden F12=Abbrechen

Die Auswahl 10 liefert eine Liste der vorgestarteten Jobeinträge, aus der man dann – je nach Treiber – den entsprechenden auswählt.

Detail von vorgestartetem Jobeintrag anzeigen

System: ADA
Subsystembeschreibung: QUSRWRK Status: ACTIVE

Programm . . . . . . . . . . . . . . . . . . . . : QZDASOINIT
Bibliothek . . . . . . . . . . . . . . . . . . : QSYS
Benutzerprofil . . . . . . . . . . . . . . . . . : QUSER
Job . . . . . . . . . . . . . . . . . . . . . . : QZDASOINIT
Jobbeschreibung . . . . . . . . . . . . . . . . : QDFTJOBD
Bibliothek . . . . . . . . . . . . . . . . . . : QGPL
Jobs starten . . . . . . . . . . . . . . . . . . : *YES
Anfängliche Anzahl Jobs . . . . . . . . . . . . : 1
Schwellenwert . . . . . . . . . . . . . . . . . : 1
Zusätzliche Anzahl Jobs . . . . . . . . . . . . : 2
Maximale Anzahl Jobs . . . . . . . . . . . . . . : *NOMAX
Maximale Anzahl Verwendungen . . . . . . . . . . : 200
Auf Job warten . . . . . . . . . . . . . . . . . : *YES
Pool-ID . . . . . . . . . . . . . . . . . . . . : 1

Weitere …
Eingabetaste –> Weiter

F3=Verlassen F12=Abbrechen F14=Vorherigen Eintrag anzeigen

Der Datenbank-Dämon des Toolbox-Treibers hat als Jobbeschreibung QDFTJOBD eingetragen; für den Native-Treiber wird in dem Eintrag auf das Benutzerprofil QUSER verwiesen: dieser Eintrag landet dann eine Stufe später ebenfalls bei derselben Jobbeschreibung QDFTJOBD.

Jobbeschreibung anzeigen

System: ADA
Jobbeschreibung: QDFTJOBD Bibliothek: QGPL

Zeitscheiben-Endepool . . . . . . . . . . . . . : *SYSVAL
Maximale Größe der Jobnachrichtenwarteschlange . : *SYSVAL
Aktion bei voller Jobnachrichtenwarteschlange . : *SYSVAL
Mehrere Threads zulassen . . . . . . . . . . . . : *NO
Text . . . . . . . . . . . . . . . . . . . . . . : Default job description

Ende
Eingabetaste –> Weiter

F3=Verlassen F12=Abbrechen

Die wahrscheinlichste Erklärung für Ihr Problem ist auf der letzten Seite der Anzeige der Jobbeschreibung mit DSPJOBD zu sehen. Die maximale Größe des Joblogs ist in jedem Fall begrenzt (8 bis 64 MB); im Systemwert QJOBMSGFL ist hinterlegt, was dann passieren soll, wenn diese Grenze erreicht ist.

Üblicherweise ist in diesem Systemwert *NOWRAP hinterlegt, was im Klartext bedeutet, den Job abzubrechen, wenn er seinen Grenzwert an Protokolleinträgen erreicht hat. Sinn und Zweck dieser Maßnahmen ist, dass ein Programm in einer Endlosschleife sein finales Ende (hoffentlich) erreicht, bevor dann spätestens die vollen Platten dem Treiben Einhalt gebieten.

Systemwert anzeigen

Systemwert . . . . . . : QJOBMSGQFL
Beschreibung . . . . . : Aktion bei voller Jobnachrichtenwarteschlange

Aktion bei voller
Jobnachrichten-
warteschlange . . . : *NOWRAP *NOWRAP
*WRAP
*PRTWRAP

Eingabetaste –> Weiter

F3=Verlassen F12=Abbrechen

In unserem Falle ist dieses Verhalten dann die wahrscheinlichste Ursache für die Fehlermeldung „Connection does not exist“. Das lässt sich noch definitiv feststellen durch die Suche nach einer entsprechenden Spoolfile für den Serverjob. Am einfachsten findet man dies zumeist über WRKJOB QZDASOINIT respektive WRKJOB QSQSRVR.

Ein Blick in solch ein Joblog lässt erkennen, dass alle SQL-Fehlercodes, die von der Datenbank zurück gegeben werden, in diesem Joblog landen – teilweise gar mehrfach. Das hat nun zur Folge, dass nach einer gewissen Anzahl von Fehlercodes die Connection abbricht. Bei Licht betrachtet ist dies eher ein Bug als ein Feature – allerdings ein Bug ohne jedes PTF; Abhilfe muss man selber schaffen.

Für die Datenbank-Serverjobs ist der Wert *WRAP für das Verhalten bei voller Jobnachrichtenwarteschlange als erwünscht anzusehen. *PRTWRAP würde zwar auch an dieser Stelle den Abbruch verhindern, führt aber zu problematischen Wartezeiten beim Überlauf. Von einer direkten Änderung des durchreferenzierten Systemwertes ist allerdings dringlich abzuraten; diese Änderung könnte auch für Jobs wirksam werden, die diese Notbremse benötigen.

Auch eine mögliche Änderung des Benutzerprofils QUSER könnte unerwünschte Seiteneffekte haben; dieses Benutzerprofil wird für die unterschiedlichsten Systemjobs verwendet und sollte normalerweise nicht leichtfertig geändert werden. Die Änderung der Jobbeschreibung QDFTJOBD verbietet sich aus den gleichen Gründen.
Am saubersten ist an dieser Stelle die Änderung der Subsystembeschreibung und die Zuordnung einer anderen Jobbeschreibung. Ein geeigneter Kandidat ist hierfür die Beschreibung für die Client Access-Hostserver QZBSJOBD. Diese unterscheiden sich von der üblichen QDFTJOBD durch die Einstellung *WRAP und das Fehlen einer Bibliothekslisten-Angabe; beide Änderungen sind für QZDASOINIT und QPWFSERV vorteilhaft und lösen das diskutierte Problem.

Alternativ dazu könnte man sich auch eine eigene Jobbeschreibung für die Database-Serverjobs erstellen. Hierzu dupliziert man die QDFTJOBD mit CRTDUPOBJ OBJ(QDFTJOBD) FROMLIB(QGPL) OBJTYPE(*JOBD) TOLIB(BENDER) NEWOBJ(DBSRVJOBD) und ändert anschließend die neu erstellte mit CHGJOBD JOBD(DBSRVJOBD) JOBMSGQFL(*WRAP).

Der wichtigste Schritt ist die Änderung der Subsystembeschreibung, die mit CHGPJE SBSD(QUSRWRK) PGM(QZDASOINIT) JOBD(QZBSJOBD) erfolgt. Für den Serverjob des Native-Treibers und die Variante mit der eigenen Beschreibung erfolgen die Änderungen analog – soweit erforderlich und gewünscht.

Sie sollten aber in jedem Fall das Design Ihrer Zugriffsschicht zur Datenbank in Ihrer Java-Anwendung einer Untersuchung unterziehen. Bei korrektem Einsatz von Connection Pooling, das so gut wie immer vorteilhaft ist, sollte das Problem nicht auftreten. Für jede Transaktion wird eine Connection vom Pool geholt und der Pool erstellt Connections von Zeit zu Zeit neu, nicht zuletzt um solchen Effekten vorzubeugen. Zudem drücken SQL-Fehlercodes auf die Performance und das massierte Auftreten könnte ein Zeichen für eine unvorteilhafte Logik sein.

Den Autor Dieter Bender erreichen Sie unter dieter.bender@midrangemagazin.de