Caché ObjectScript Reference
TROLLBACK
[Home] [Back] [Next]
InterSystems: The power behind what matters   
Class Reference   
Search:    

Rolls back an unsuccessful transaction.
Synopsis
TROLLBACK:pc
TRO:pc

TROLLBACK:pc 1
TRO:pc 1
Arguments
pc Optional — A postconditional expression.
1 Optional — The integer 1. Rolls back one level of nesting. Must be specified as a literal.
Description
TROLLBACK terminates the current transaction and restores all journaled database values to the values they held at the start of the transaction. TROLLBACK has two forms:
You can determine the level of nested transactions from the $TLEVEL special variable. Calling TROLLBACK when $TLEVEL is 0 has no effect.
You can use the GetImageJournalInfo() method of the %SYS.Journal.System class to search the journal file for TSTART commands, and thus identify open transactions. A TSTART increments $TLEVEL and writes a journal file record: either a “BT” (Begin Transaction) record if $TLEVEL was zero, or a “BTL” (Begin Transaction with Level) record if $TLEVEL was greater than 0. Use the Sync() method of the %SYS.Journal.System class to flush the journal buffer following a successful rollback operation.
TROLLBACK disables Ctrl-C interrupts for the duration of the rollback operation.
What Is and Isn’t Rolled Back
TROLLBACK rolls back all journaled operations. These include the following:
However, not all changes made by an application are journaled:
Caché treats a SET or KILL of a global variable as a journaled transaction event; rolling back the transaction reverses these operations. Caché does not treat a SET or KILL of a local variable or a process-private global variable as a journaled transaction event; rolling back the transaction has no effect on these operations. By default, a SET or KILL of a global variable is immediately visible by other processes while the transaction is in progress. To prevent the SET or KILL of a global variable invoked within a transaction from being seen by other users before the transaction has been committed, you must coordinate access to the global variable via the LOCK command.
Transaction Rollback Logging
If an error occurs during a roll back operation, Caché issues a <ROLLFAIL> error message, and logs an error message in the cconsole.log operator console log file. You can use the Management Portal System Operation option to view cconsole.log: [Home] > [System Logs] > [View Console Log].
By default, the operator console log file is cconsole.log in the Caché system management directory (Mgr). This default is configurable. Go to the Management Portal System Administration option, select Configuration, then Additional Settings, then Advanced Memory ([Home] > [Configuration] > [Advanced Memory Settings]). View and edit the current setting of ConsoleFile. By default this setting is blank, routing console messages to cconsole.log in the MGR directory. If you change this setting, you must restart Caché for this change to take effect.
<ROLLFAIL> Errors
If TROLLBACK cannot successfully roll back the transaction, a <ROLLFAIL> error occurs. The process behavior depends on the setting of the system-wide journal configuration setting flag Freeze on error ([Home] > [Configuration] > [Journal Settings]):
For further details, refer to Journal IO Errors in the Caché Data Integrity Guide.
When a <ROLLFAIL> occurs, the Caché %msg records both the <ROLLFAIL> error itself, and the previous error that caused the roll back. For example, attempting to update a date with an out-of-range value and then failing roll back might return the following %msg: SQLCODE = -105 %msg = Unexpected error occurred: <ROLLFAIL>%0Ac+1^dpv during TROLLBACK. Previous error: SQLCODE=-105, %msg='Field 'Sample.Person.DOB' (value '5888326') failed validation'.
A <ROLLFAIL> occurs upon transaction rollback if within the transaction a global accessed a remote database, and then the program explicitly dismounted that remote database.
A <ROLLFAIL> occurs upon transaction rollback if the process disabled journaling before making database changes and an error occurred that invoked transaction rollback. A <ROLLFAIL> does not occur upon transaction rollback if the process disabled journaling after all database changes had been made but before issuing the TROLLBACK command. Instead, Caché temporarily enables journaling for the duration of the rollback operation. Upon completion of the rollback operation Caché again disables journaling.
SQL and Transactions
ObjectScript and SQL transaction commands are fully compatible and interchangeable, with the following exception:
ObjectScript TSTART and SQL START TRANSACTION both start a transaction if no transaction is current. However, START TRANSACTION does not support nested transactions. Therefore, if you need (or may need) nested transactions, it is preferable to start the transaction with TSTART. If you need compatibility with the SQL standard, use START TRANSACTION.
ObjectScript transaction processing provides limited support for nested transactions. SQL transaction processing supplies support for savepoints within transactions.
Purging Cached Queries
If during a transaction you call the Purge() method of %SYSTEM.SQL class to purge cached queries, the cached queries are permanently deleted. A subsequent TROLLBACK will not restore purged cached queries.
Globals and TROLLBACK 1
TROLLBACK 1 rolls back and restores all globals changed within its nested transaction. However, if globals are changed that are mapped to a remote system that does not support nested transactions, these changes are treated as occurring at the outermost nested level. Such globals are only rolled back when a rollback resets $TLEVEL to 0, either by calling TROLLBACK or by calling TROLLBACK 1 when $TLEVEL=1.
Locks and TROLLBACK 1
TROLLBACK 1 does not restore locks established during its nested transaction to their prior state. All locks established during a transaction remain in the lock table until the transaction is concluded by a TROLLBACK to level 0 or a TCOMMIT. At that point Caché releases all locks created during the nested transaction, and restores all preexisting locks to their state before TSTART.
A TCOMMIT of a nested transaction does not release the corresponding locks, so a subsequent TROLLBACK can effect locks in a committed sub-transaction.
Arguments
pc
An optional postconditional expression. Caché executes the command if the postconditional expression is true (evaluates to a nonzero numeric value). Caché does not execute the command if the postconditional expression is false (evaluates to zero). For further details, refer to Command Postconditional Expressions in Using Caché ObjectScript.
Examples
The following example uses a single-level transaction to transfer a random amount of money from one account to another. If the transfer amount is more than the available balance, the program uses TROLLBACK to roll back the transaction:
SetupBankAccounts
   SET num=12345
   SET ^CHECKING(num,"balance")=500.99
   SET ^SAVINGS(num,"balance")=100.22
   IF $DATA(^NumberOfTransfers)=0 {SET ^NumberOfTransfers=0}
BankTransfer
   WRITE "Before transfer:",!,"Checking=$",^CHECKING(num,"balance")," Savings=$",^SAVINGS(num,"balance"),!
   // Transfer funds from one account to another
   SET transfer=$RANDOM(1000)
   WRITE "transfer amount $",transfer,!
   DO CkToSav(num,transfer)
   IF ok=1 {WRITE "sucessful transfer",!,"Number of transfers to date=",^NumberOfTransfers,!}
   ELSE {WRITE "*** INSUFFICIENT FUNDS ***",!}
   WRITE "After transfer:",!,"Checking=$",^CHECKING(num,"balance")," Savings=$",^SAVINGS(num,"balance"),!
   RETURN
CkToSav(acct,amt)
  TSTART
  SET ^CHECKING(acct,"balance") = ^CHECKING(acct,"balance") - amt
  SET ^SAVINGS(acct,"balance") = ^SAVINGS(acct,"balance") + amt
  SET ^NumberOfTransfers=^NumberOfTransfers + 1
  IF ^CHECKING(acct,"balance") > 0 {TCOMMIT  SET ok=1 QUIT:ok}
  ELSE {TROLLBACK  SET ok=0 QUIT:ok}
 
The following example shows the effects of TROLLBACK on nested transactions. Each TSTART increments $TLEVEL and sets a global. Issuing a TCOMMIT on the inner nested transaction decrements $TLEVEL, but the commitment of changes made in a nested transaction is deferred. In this case, the subsequent TROLLBACK on the outer transaction rolls back all changes made, including those in the inner “committed” nested transaction.
  SET ^a(1)="[- - -]",^b(1)="[- - -]"
  WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
  TSTART
   LOCK +^a(1)
   SET ^a(1)="hello"
   WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
     TSTART
     LOCK +^b(1)
     SET ^b(1)="world"
     WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
     TCOMMIT
  WRITE !,"After TCOMMIT"
  WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
  TROLLBACK
  WRITE !,"After TROLLBACK"
  WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
  QUIT
 
The following example shows how TROLLBACK rolls back global variables, but not local variables:
  SET x="default",^y="default"
  WRITE !,"level:",$TLEVEL
  WRITE !,"local:",x," global:",^y
  TSTART
  SET x="first",^y="first"
  WRITE !,"TSTART level:",$TLEVEL
  WRITE !,"local:",x," global:",^y
    TSTART
    SET x=x_" second",^y=^y_" second"
    WRITE !,"TSTART level:",$TLEVEL
    WRITE !,"local:",x," global:",^y
     TSTART
     SET x=x_" third",^y=^y_" third"
    WRITE !,"TSTART level:",$TLEVEL
    WRITE !,"local:",x," global:",^y
  TROLLBACK
  WRITE !!,"After Rollback:"
  WRITE !,"TROLLBACK level:",$TLEVEL
  WRITE !,"local:",x," global:",^y
 
The following example shows how $INCREMENT changes to a global are not rolled back.
  SET ^x=-1,^y=0
  WRITE !,"level:",$TLEVEL
  WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
  TSTART
  SET ^y=^y+1
  WRITE !,"level:",$TLEVEL
  WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
    TSTART
    SET ^y=^y+1,^z=^z_" second"
    WRITE !,"level:",$TLEVEL
    WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
     TSTART
     SET ^y=^y+1,^z=^z_" third"
     WRITE !,"level:",$TLEVEL
     WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
  TROLLBACK
  WRITE !!,"After Rollback"
  WRITE !,"level:",$TLEVEL
  WRITE !,"Increment:",^x," Add:",^y
 
See Also