The programming practice of fencing logical transactions protects database integrity during a system interruption. A logical transaction is a logical unit that is not complete unless all parts of the transaction are captured. For instance, the logical transaction "transfer funds between accounts" consists of a debit update to one account and a credit update to another account.
Establishing fences around a logical transaction assures that the transaction is committed as a unit, thereby avoiding logical inconsistencies. These logical inconsistencies, sometimes referred to as application-level database integrity problems, manifest themselves as run-time errors, inappropriate branching, and incorrect reports.
In GT.M, there are two methods of defining application transaction boundaries. One method is using the transaction commands TSTART and TCOMMIT. The other method uses the GT.M journal fencing commands ZTSTART and ZTCOMMIT.
TSTART or ZTSTART activate transaction fence control. Subsequent SETs and KILLs across all accessed regions are marked as belonging to a fenced transaction. The TCOMMIT or ZTCOMMIT commands respectively, close the fenced transaction and write the TCOMMIT and ZTCOMMIT journal records in all the journal files of all regions involved in the transaction.
If a TSTART has been processed, and another TSTART is encountered prior to a TCOMMIT, then the second TSTART does not cause another fence to be emitted to the journal file, instead increments a "transaction depth" counter accessible as $TLEVEL. Succeeding TCOMMIT directives cause decrementing of this transaction depth counter. The TCOMMIT fence is emitted to the journal file when the "transaction depth" returns to zero (0) (such occurrences are referred to as "nested" transactions or sub-transactions).
The maximum depth of a TP transaction nesting is 127 levels.
Similarly, if a ZTSTART has been processed, and another ZTSTART is encountered prior to a ZTCOMMIT, then the second ZTSTART does not cause another fence to be emitted to the journal file. Instead the second ZTSTART increments a "transaction depth" counter. Succeeding ZTCOMMIT directives cause decrementing of this transaction depth counter. The ZTCOMMIT fence is emitted to the journal file when the "transaction depth" returns to zero (0) (such occurrences are referred to as "nested" transactions or sub-transactions).
The maximum depth of a ZTSTART transaction nesting is 255 levels.
The command ZTCOMMIT numexpr where numexpr is greater than zero (0), is functionally equivalent to the code:
X "NEW X F X=1:1:numexpr ZTCOMMIT"
and the command ZTCOMMIT 0 is equivalent to the command:
ZTCOMMIT $VIEW("JNLTRANSACTION")
This essentially means, ZTCOMMIT 0 closes the transaction, and any and all open sub-transactions.
Negative values of numexpr are erroneous.
In case of TSTART/TCOMMIT, journal records for all fenced updates involved in the transaction are written to journal files of all regions only during the time of TCOMMIT, that is, only when the TCOMMIT journal records get written. While, in the case of ZTSTART/ZTCOMMIT, journal records are written as and when each SET or KILL is encountered in the fenced transaction.
While TSTART and TCOMMIT produce transactions with ACID properties (when certain conventions are followed), ZTSTART and ZTCOMMIT do not modify M semantics at all. These commands only generate fencing information in the journals. The M and Z transaction commands cannot be mixed in a single transaction. MUPIP JOURNAL uses the information provided by TSTART and TCOMMIT or ZTSTART and ZTCOMMIT, to restore the entire set of updates that comprise the transaction (unless specifically instructed to restore only part of the update).
Using TSTART and TCOMMIT or ZTSTART and ZTCOMMIT significantly improves the benefit of journaling. When recovering from journal files, MUPIP JOURNAL -RECOVER processing by default recovers either all updates within the transaction fences or none of them, and reports the latter case during recovery.
In MUPIP documentation, the term transaction means "database update".