Database coordination
When the queue manager coordinates global units of work itself, it becomes possible to integrate database updates within the units of work. That is, a mixed MQI and SQL application can be written, and the MQCMIT and MQBACK verbs can be used to commit or roll back the changes to the queues and databases together.
The queue manager achieves this using the two-phase commit protocol described in X/Open Distributed Transaction Processing: The XA Specification. When a unit of work is to be committed, the queue manager first asks each participating database manager whether it is prepared to commit its updates. Only if all the participants, including the queue manager itself, are prepared to commit, are all the queue and database updates committed. If any participant cannot prepare its updates, the unit of work is backed out instead.
In general, a global unit of work is implemented in an application by the following method (in pseudocode):- MQBEGIN
- MQGET (include the flag MQGMO_SYNCPOINT in the message options)
- MQPUT (include the flag MQPMO_SYNCPOINT in the message options)
- SQL INSERT
- MQCMIT
- The application programmer can force a unit of work to be backed out by calling MQBACK. The unit of work is also backed out by the queue manager if the application or database fails before MQCMIT is called.
- If an application calls MQDISC without calling MQCMIT, the queue manager behaves as if MQCMIT had been called, and commits the unit of work.
In between MQBEGIN and MQCMIT, the queue manager does not make any calls to the database to update its resources. That is, the only way a database's tables are changed is by your code (for example, the SQL INSERT in the pseudocode).
Full recovery support is provided if the queue manager loses contact with any of the database managers during the commit protocol. If a database manager becomes unavailable while it is in doubt, that is, it has successfully prepared to commit, but has yet to receive a commit or backout decision, the queue manager remembers the outcome of the unit of work until that outcome has been successfully delivered to the database. Similarly, if the queue manager terminates with incomplete commit operations outstanding, these are remembered over queue manager restart. If an application terminates unexpectedly, the integrity of the unit of work is not compromised, but the outcome depends on where in the process the application terminated, as described in Table 2.
What happens when the database or application program fails is summarized in the following tables:Failure occurrence | Outcome |
---|---|
Before the application call to MQCMIT. | The unit of work is backed out. |
During the application call to MQCMIT, before all databases have indicated that they have successfully prepared. | The unit of work is backed out with a reason code of MQRC_BACKED_OUT. |
During the application call to MQCMIT, after all databases have indicated that they have successfully prepared, but before all have indicated that they have successfully committed. | The unit of work is held in recoverable state by the queue manager, with a reason code of MQRC_OUTCOME_PENDING. |
During the application call to MQCMIT, after all databases have indicated that they have successfully committed. | The unit of work is committed with a reason code of MQRC_NONE. |
After the application call to MQCMIT. | The unit of work is committed with a reason code of MQRC_NONE. |
Failure occurrence | Outcome |
---|---|
Before the application call to MQCMIT. | The unit of work is backed out. |
During the application call to MQCMIT, before the queue manager has received the application's MQCMIT request. | The unit of work is backed out. |
During the application call to MQCMIT, after the queue manager has received the application's MQCMIT request. | The queue manager tries to commit using two-phase commit (subject to the database products successfully executing and committing their parts of the unit of work). |
In the case where the reason code on return from MQCMIT is MQRC_OUTCOME_PENDING, the unit of work is remembered by the queue manager until it has been able to reestablish contact with the database server, and tell it to commit its part of the unit of work. Refer to Considerations when contact is lost with the XA resource manager for information on how and when recovery is done.
The queue manager communicates with database managers using the XA interface as described in X/Open Distributed Transaction Processing: The XA Specification. Examples of these function calls are xa_open, xa_start, xa_end, xa_prepare, and xa_commit. We use the terms transaction manager and resource manager in the same sense as they are used in the XA specification.