MainframeSupports
tip uge 18/2007:

Messages i MQ kan skrives og læses uden at være omfattet af nogen form for commit/syncpoint kontrol. Det styrer du med parameteren MQPMO_NO_SYNCPOINT (PUT) eller MQGMO_NO_SYNCPOINT (GET). Hvis du benytter NO_SYNCPOINT vil din message blive sendt med det samme ved PUT og forsvinde fra køen med det samme ved GET. Især ved GET skal du være opmærksom på, at med MQGMO_NO_SYNCPOINT så er den GET'tede message tabt for altid, med mindre du selv skriver den tilbage.

Anderledes er det med MQPMO_SYNCPOINT og MQGMO_SYNCPOINT. Ved PUT sendes messagen først, når der udstedes en MQCMIT (under CICS en EXEC CICS SYNCPOINT) enten explicit eller implicit ved, at programmet/task'et afsluttes normalt. Ved GET får du fat i messagens indhold med det samme, men messagen forsvinder først fra MQ, når der committes. Hvis programmet/task'et abend'er eller på anden måde ruller tilbage (eksempelvis pga. en MQBACK eller en EXEC CICS SYNCPOINT ROLLBACK), så sendes messagen ikke ved PUT (den slettes fra MQ) og ved GET forbliver messagen på MQ køen. Der er atså sket en backout af MQ messages.

Nu er det, at du nemt kan løbe ind i store problemer. Hvis grunden til, at dit program foretager backout skyldes indholdet af en af de MQ messages, du har fået foretaget backout af, så vil fejlen med stor sandsynlighed genopstå, når du igen forsøger at GET'te den fejlbehæftede message, som på grund af backout'en stadig ligger på MQ køen. En af de mest berømte loops i MQ applikationer forekommer netop på grund af dette problem. For de af jer, der ikke har prøvet det, så opstår loop'et, når den første message ankommer på en MQ kø, som så trigger en CICS transaktion. CICS transaktionen abender, messagen ryger tilbage på MQ køen og trigger som den første message på køen igen CICS transaktionen og så fremdeles.

Heldigvis løb man under udvilkingen af MQ hurtigt ind i dette problem og opfandt et felt i message descriptoren (MQMD) kaldet backoutCount, som sættes til 0 ved MQPUT og som tælles een op, hver gang messagen udsættes for en backout. Hvis du laver MQGET af messages med MQGMO_SYNCPOINT skal du for at undgå de beskrevne problemer kode noget i stil med:

call MQGET...
if mqReturnCode = 0
  if mqmd.backout > 0
    ...Gem fejlet message...
  else
    ...normal behandling af message...
else
  ...fejlbehandling...

I eksemplet har jeg foreslået, at du gemmer den fejlede message. Det kan du gøre på en anden MQ kø. Det kalder nogen for en backout kø. Du kan også gemme messagen i DB2. Ideen er under alle omstændigheder, at du gemmer den, så du kan finde ud af, hvad der er galt med den, eventuelt rette den og så sende den til behandling igen. Du kan selvfølgelig også bare ignorere den fuldstændig.

Der findes i øvrigt en attribut på en MQ kø kaldet "harden backout counter". Hvis du sætter dette felt til "Y", så vil MQ sørge for at tælle backout counteren op selv når MQ er ved at gå ned. Denne attribut giver i øvrigt kun mening for persistente køer, som netop kendetegnes ved at overleve et MQ nedbrud eller almindelig genstart af MQ. Attributten giver simpelthen øget sikkerhed for nøjagtigheden af backoutCount feltet i MQMD, men har derudover ingen indflydelse på backoutCount.

Du kan læse meget mere om backout i WebSphere MQ Application Progamming Reference. OBS. Linket er til en PDF download af manualen, da der ikke findes en HTML udgave på IBMs Library Server. Hvis du ikke har en hurtig ADSL forbindelse, så lad være med at klikke på linket. Det tager laaaaang tid at download'e manualen.

Forrige danske tip        Last tip in english        Tip oversigten