Hi Curt,
Morag's idea is a good idea - it could be a duplicate message on the queue - I had not thought of that.
If you can print the date time from the message (for example in hex) it would tell us if it is the same message or a different message.
There is also
MQMD-Backout count which tells you how many times the message has been backed out. If you can display this value as well, it would help see if the message was backed out or not.If the application did a exec cics rollback, it would get the cause the message to become available. The transaction does not have to abend.
The fact that the "duplicate" message is discovered almost immediately after the first attempt at processing is a good sign. If you take a trace, then the records would be very close in the trace. If it was minutes apart it would be hard to capture the correct traces.
Some options I see are
CICS dump.
If you can put an
EXEC CICS DUMP SYSTEM into your program when you detect the duplicate message, and turn CICS trace on for that transaction you will get out a dump with the internal trace, and the internal trace should have your transactions in them.
CICS TRACE
Use CICS aux trace, and disable the trace when the problem occurs.
I think you can trace just the mq component, and for the specific transaction. (CETR?)
MQ API trace. This puts data to GTF. It does not have fine granularity, and you might get a lot of data.
My CICS is a bit rusty - I haven' used it for about 10 years.
regards
Colin
------------------------------
Colin Paice
------------------------------
Original Message:
Sent: Wed June 22, 2022 10:03 PM
From: Morag Hughson
Subject: MQ message delivered to more than one transaction?
That is very good news Curt. We certainly wouldn't want the application to put duplicate messages. I am happy to hear that you have ruled that out as a problem. Is there just a single putting application? I'm not sure that you described the upstream application workflow to us - we have a detailed description of the getters and the triggering of those transactions. Can you show us how messages get to the Fill Queue?
Cheers,
Morag
------------------------------
Morag Hughson
MQ Technical Education Specialist
MQGem Software Limited
Website: https://www.mqgem.com
Original Message:
Sent: Wed June 22, 2022 09:38 PM
From: Curt Gilker
Subject: MQ message delivered to more than one transaction?
I am not doing a COBOL DISPLAY of the MQMD-MSGID after each successful MQGET. I cound do that, as a proof, but the application that PUTs to my input queue does not PUT duplicate messages on it.
------------------------------
Curt Gilker
Original Message:
Sent: Wed June 22, 2022 09:29 PM
From: Morag Hughson
Subject: MQ message delivered to more than one transaction?
I am happy to hear that you don't have that problem. Can you share with us why you have that confidence? Perhaps you are also doing a COBOL DISPLAY of the MQMD-MSGID after each successful MQGET? Or perhaps you have got tracing of the issue by now and can see the message ID from there?
Cheers,
Morag
------------------------------
Morag Hughson
MQ Technical Education Specialist
MQGem Software Limited
Website: https://www.mqgem.com
Original Message:
Sent: Wed June 22, 2022 08:43 PM
From: Curt Gilker
Subject: MQ message delivered to more than one transaction?
Hi Morag
You are correct, this is not the MQMD-MSGID generated field. This is the message data, i.e. the contents of the MQ message.
I am confident that there is only one message in the input queue with this data in the contents.
------------------------------
Curt Gilker
Original Message:
Sent: Wed June 22, 2022 07:14 PM
From: Morag Hughson
Subject: MQ message delivered to more than one transaction?
Don't give up yet Curt. With something like this, the devil is in the detail, but we can find those details.
Thank you for sharing the DISPLAY statements you found with us. I am sure they will help. Could you tell us what field the "BETF-255736737" data came from? For example, was it the MQMD-MSGID field?
The contents of the data you have shown us does not look like a queue manager generated message ID value (those have the queue manager name in them with some well known prefix characters). Do you know who generates that data - the application that put the message for example? The fact that you use that value as a primary key to do a DB2 insert also suggests that it is not a queue manager generated message ID value, but something generated by an application that has more awareness of the "shape" of the data to be used as a key.
One hypothesis that might be worth following up, is, do you have two messages on this queue with the same "BETF-255736737" data in them? That would certainly fit the description of the problem you have provided so far.
Cheers,
Morag
------------------------------
Morag Hughson
MQ Technical Education Specialist
MQGem Software Limited
Website: https://www.mqgem.com
Original Message:
Sent: Wed June 22, 2022 02:09 PM
From: Curt Gilker
Subject: MQ message delivered to more than one transaction?
Hi Colin
I don't know if our facility has used the CICS trace capability. But I have discovered some additional information. Note that what I am about to say does not mean that I don't believe that MQ has a bug, I just cannot yet 'see' the root cause of what is happening:
I have added additional diagnostic data to my program. And today, I see the following in the log:- BET2 20220622095206 ADVOC417: MQ INPUT: BETF-255736737 (this is a COBOL DISPLAY statement that shows that CICS transaction BET2 did an MQGET of the message BETF-255736737 at 09:52:06)
Shortly thereafter, I see the following in the log:- BET1 20220622095206 ADVOC417: MQ INPUT: BETF-255736737 (this is a COBOL DISPAY statement that shows that CICS transaction BET1 did an MQGET of the message BETF-255736737 at 09:52:06)
There is no evidence that transaction BET2 abended (i.e. triggering a rollback of the MQ message) between the time that BET2 did its' MQGET and the time that BET1 did its' MQGET (A more granular timestamp would admittedly have been more helpful here).Instead, the abend occurs later, on BET2's attempt to do a DB2 insert using the value of the MQ message (255736737) as a primary key, with a SQLCODE -803. This is because BET1 had already performed that insert (using the same value), presumably just milliseconds before (I am getting the DB2 log data to verify this, but I see the row in the database).
And I have found several other identical examples to the above scenario. Now, as I said, I do not question MQ. I just cannot figure out how / why this is happening. I am about ready to give up on this :(
------------------------------
Curt Gilker
Original Message:
Sent: Wed June 22, 2022 04:24 AM
From: Colin Paice
Subject: MQ message delivered to more than one transaction?
Curt,
You may be able to turn on CICS aux trace for just that transaction and then search for the backout/rollback when the problem has been detected.
Colin
------------------------------
Colin Paice
Original Message:
Sent: Tue June 21, 2022 09:36 AM
From: Curt Gilker
Subject: MQ message delivered to more than one transaction?
Hi Colin
I am convinced you are correct, that a rollback is occurring in one of my transactions. Unfortunately, I have yet to find where it occurs, as my transactions are calling several (many?) legacy programs that do quite a bit of processing, and (in my opinion) do some funky error handling. I am concerned that one of them determines that a rollback is needed.
Nevertheless, you have confirmed my belief. So now I need to dig into where the issue lies. I think I know where to find the CICS stats, but I will have to look for the MQ accounting data.
Many thanks!
------------------------------
Curt Gilker
Original Message:
Sent: Tue June 21, 2022 04:28 AM
From: Colin Paice
Subject: MQ message delivered to more than one transaction?
Hi Curt,
Thanks for your update.
The doc for triggering says If the application queue is open for input, by any program, and has triggering set for FIRST or DEPTH, no trigger event occurs because the queue is already being served.
So if no queue has the queue open for input then the first message will cause a trigger message to be produced - and so start a transaction.
If there is at least one application with the queue open for input, then there will not be a trigger message produced.
I would expect from what you said that only one transaction (BET1) runs. If BET1 closes the queue, and there is a message on the queue (due to bad timing) it will cause another trigger message, and so may possibly start BET2.
Despite this, non of this triggering will cause a message to be processed more than once.
_________________________________________________
"MQ delivers the message twice"...
Consider the scenario
MQGET of message1
do something - for example write to TD queue (not in syncpoint) 'Ive processed message 1'
Rollback
Transaction ends
Triggering starts up a new transaction
transaction starts
MQGET of message1
do something - for example write to CICS TD queue (not in syncpoint) 'Ive processed message 1'
commit
Transaction ends
So in your CICS TD queue you have 2 instances of 'Ive processed message 1', and you say "Ah Ha - MQ has delivered the message more than once".
If would be worth putting some code in your transactions to report if the application did a roll back. This is good practice, as you should investigate why it has rolled back. (For example if a DB2 request timed out, you should investigate this)
From the MQ accounting data you will see if there is a rollback or commit.
I cant remember if the CICS stats report the number of commits and backouts, it would be worth looking there.
Putting a few lines of code in your program to say a rollback has occurred ( and why) would be good practice, and be less disruptive to turning on trace or accounting.
Colin
------------------------------
Colin Paice
Original Message:
Sent: Mon June 20, 2022 09:26 AM
From: Curt Gilker
Subject: MQ message delivered to more than one transaction?
Hi Colin - thank you for replying to my query.
I think we are on the same page, terminology-wise. I used imprecise language when I said "a message in the queue is delivered to more than one transaction." What I should have said was "MQ appears to be returning the same message to more than one transaction when the transactions do an MQGET."
This may be a fuller description of the design pattern:
Create 8 BETx transactions, all driven by the same program (BET1, BET2, etc)
ADV.ETF.FILL.QUEUE to trigger transaction BETA on first message written to the queue
Transaction BETA does an EXEC CICS START of a BETx clone each time it is triggered (i.e. for only one message in the queue):
- do a CICS ENQ RESOURCE on BET1, BET2, etc. until we find a BETx transaction that is not running. START that one, then end
- If all 8 BETx transactions are already running, end
In short, BETA STARTs the first BETx clone that is not already executing. Wait Y seconds, then end (BETA waits a few seconds for the STARTed transaction to GET the message from the queue).
The BETx clone does an MQGET from the queue, processes it, then continues processing the queue until it is empty.
And here is my visual representation:
------------------------------
Curt Gilker
Original Message:
Sent: Sat June 18, 2022 08:28 AM
From: Colin Paice
Subject: MQ message delivered to more than one transaction?
Hi Curt,
There are several concept things I need to explain.
Browse/destructure get
You can do a browse of a message on the queue. Two applications can browse the same message on the queue.
You can do a destructive get of a message on the queue. The message is locked to the first transaction and that does a destructive get. Only one application will get the message.
Syncpoint.
This does not affect the visibility - or the number of transactions that can get the message.
- No-Syncpoint is a (get + commit)
- Syncpoint means that you need an explicit commit for the message to removed from the system. You typically do an MQget , DB2 update commit. The doc says CICS® applications must use the
EXEC CICS SYNCPOINT
command to commit the unit of work explicitly. Alternatively, ending the transaction results in an implicit commit of the unit of work. So if the transaction fails to issue exec CICS syncpoint, it will be done for you
Input-shared
This means that more than one application can have the queue open for input at the same time. It is independent to Sync-point, and destructive get |browse .
Clarification.
When you said
"What I am seeing, in some cases, is that a message in the queue is delivered to more than one transaction." The most common pattern is applications get a message rather than be given in. There is a model where a long running transaction gets data from the queue, and does a start transaction(.....) data(....), commit. So the get and the start request are in a unit of work, and the transaction is given the message. There should be one transaction per message. I do'nt think you have this situation.
There is a more sophisticated model where a message is browsed (and "locked" making it invisible) by a long running application, and a CICS transaction is started passing the message id. You can specify a "locked" duration which says if the messages hasnt been got within this time interval, then unlock it after this time. The next pass of this queue, spots the message is now visible and it can start another message. The message should only be go once (unless it is browsed)
Please can you clarify what the application does.
Colin
------------------------------
Colin Paice
Original Message:
Sent: Fri June 17, 2022 04:25 PM
From: Curt Gilker
Subject: MQ message delivered to more than one transaction?
I have a local MQ on z/OS that is read (consumed) by several CICS transactions. Each transaction is processed by the same program, so this is an attempt to multi-process the input queue using multiple duplicate transactions.
What I am seeing, in some cases, is that a message in the queue is delivered to more than one transaction.
Each transaction opens the queue using the option MQOO-INPUT-SHARED, and each transaction does the MQGET using the installation default for option MQGMO-SYNCPOINT / MQGMO-NO-SYNCPOINT.
I am 99% certain that the installation default is MQGMO-SYNCPOINT (since if I issue a CICS SYNCPOINT ROLLBACK the message is restored to the queue, whereas I understand that under MQGMO-NO-SYNCPOINT the message is message is deleted from the queue immediately, and cannot be made available again by backing out the unit-of-work).
Under the above, I do not believe that the MQGET from a transaction would ever result in MQ delivering the same message to more than one transaction, even when they are different units-of-work.
Am I missing something?
------------------------------
Curt Gilker
------------------------------