Transaction difference between MiniM and Cache
On application development with transactions and on porting applications MUMPS developers must understand some internals and how it works. This article describes two differences between transaction processing in MiniM and Cache.
Both systems operates in transaction-oriented models for rollback made changes. Commit operations are only starting points for internal mechanisms and both servers perform the actual work only when the transaction is rolled back. Both systems have almost identical behavior and architecture of the rollback transactions built on logging, including the ability to process temporary turn off logging and turn back.
Rolling back the transaction involves a formal restoration of data, modified in transactions in their original condition. MiniM Database Server fully follows this definition. When processes change globals, all changes are journaled. If job commit a transaction, these journals records are no longer required other than to restore from backup. On rollback transaction server scans the journal entries including entries not yet recorded on the disk (the journaling cache) and returns the globals to the initial state, that was before the changes made in the transaction.
When transaction rolled back MiniM reviews all journal entries the transaction prior to its start. The number of taken changes and its types does not matter, they will all be rolled back and server imposes no restrictions (except for records created by the function $increment(), these records are not rolled back ever).
This is the first difference of servers MiniM Database Server and Cache. Unlike of MiniM, Cache can perform only a limited number of rollbacks removal of globals for the kill command if the command is also removing nested subscripts. In the case of the transaction will remove more than can roll Cache, part of the deletions would not be restored. Therefore, the designer of applications for Cache must consider in what mode and how many deletions will be performed. In this situation MiniM Database Server rolls back all changes made within the transaction.
Example of execution rollback in Cache:
USER>k ^b s ^b=100000 USER>f i=1:1:^b s ^b(i)=1 USER>ts USER>f i=1:1:^b k ^b(i) USER>tro USER>w $o(^b("")),!,$o(^b(""),-1),! 1 100000 USER>ts k ^b tro USER>w $o(^b("")),!,$o(^b(""),-1),! 1 1000
The same operations in MiniM:
USER>k ^b s ^b=100000 USER>f i=1:1:^b s ^b(i)=1 USER>ts USER>f i=1:1:^b k ^b(i) USER>tro USER>w $o(^b("")),!,$o(^b(""),-1),! 1 100000 USER>ts k ^b tro USER>w $o(^b("")),!,$o(^b(""),-1),! 1 100000
This example demonstrates that on the k ^b command inside transaction Cache server can roll back only a part of kills made and MiniM server rolls back all changes.
MiniM Database Server rolls back global's changes into state on the change moment but not to transaction start state and rolls back only changes made by the current job.
On rolling back MiniM Database Server does not see was or not any changes made with this global by other jobs and all changes made by job rolls back in any case. Cache can roll back or not roll back globals changes in dependence was or not this global changed by the other job.
For example we use two jobs and the following commands sequence in Cache:
First job Second job USER>k ^b USER>ts USER>s ^b(1)=1,s ^b(2)=2 USER>s ^b(2)=22 USER>tro USER>zw ^b ^b(2)=22
The same commands sequence in the MiniM:
First job Second job USER>k ^b USER>ts USER>s ^b(1)=1,^b(2)=2 USER>s ^b(2)=22 USER>tro USER>zw ^b
Here we can see that MiniM rolls back all changes independently of was or not any changes made by other jobs.
This transaction difference also includes the kill command or change global variable to UNDEFINED state.
Code execution with two jobs in Cache:
First job Second job USER>k ^a USER>s ^a(1)=1,^a(2)=2,^a(3)=3 USER>ts USER>s ^a(2)=22 USER>k ^a USER>tro USER>zw ^a USER>
The same situation in the MiniM:
First job Second job USER>k ^a USER>s ^a(1)=1,^a(2)=2,^a(3)=3 USER>ts USER>s ^a(2)=22 USER>k ^a USER>tro USER>zw ^a ^a(2)=2 USER>
This example show that MiniM job on rollback was found journal record about changed global variable ^a(2) and restores this variable into original state which was before changing and Cache job accepts changes made by second job and does not revert global changes made within transaction.
I think, the better way to write portable applications is using the lock command. Both systems holds locks made within transaction, so two or more jobs cannot change locked globals.Eugene Karataev