Transaction Fencing and LOCKs

LOCKs and ZTSTART and ZTCOMMIT transaction fences have an important relationship. MUPIP JOURNAL /RECOVER assumes that fenced transactions are isolated and never performs a cascading roll-back. The term cascading roll-back describes the situation that occurs when dropping one transaction causes previous transactions to be sequentially dropped, until potentially all transactions are dropped. If an application violates this assumption, a JOURNAL /RECOVER may create a database with application-level integrity problems. M LOCKs ensure the isolation of a sequence of updates from interaction with any other updates. TSTART and TCOMMIT transaction fences implicitly exhibit the required isolation whether fences are used with or without associated LOCKs.

Example of a non-isolated transaction:

Process A                    Process B
---------                    ---------
ZTS
S ^(acct)=^AMT(d,acct)+amt
                             ZTS
                             S ^(acct)=^AMT(d,acct)+amt
                             S (j,^(0))=^JNL(acct,0)+1
                             S ^JNL(acct,j)=stf
                             ZTC
S (j,^(0))=^JNL(acct,0)+1
                   -- failure --

These two sets of transactions are not isolated from each other. After the system fails, Process A's transaction must be removed by a /RECOVER /BACKWARD or not replayed by a / RECOVER /FORWARD. However, if acct has the same value for both processes when Process B's transaction is recovered, ^AMT(d,acct) includes Process A's amt as well as Process B's amt.

Adding a LOCK to the program (e.g., L ^JNL(acct) just before the ZTSTART and a LOCK with no argument after the ZTCOMMIT,) isolates the transactions and prevents the two processes from overlapping. Because M does not treat the SET command as an atomic database operation, in the absence of TSTART/TCOMMIT commands, such LOCKs should exist independent of journaling considerations to protect the updates to ^AMT(d,acct) and ^JNL(0).