Is there a way to omit or skip rollback of some data changes during a transaction rollback?

Is there a way to omit or skip rollback of some data changes during a transaction rollback? Maybe some sort of "autonomous transaction"?

The issue is with error logging in transaction. For example we may have in nested calls the following structure:
TS
<some code>
<error happens>
TRO 1
<error log to database>

but if this code is in another transaction, and that rolls back we lose error data.

Is there a way to do something like
TS
<some code>
<error happens>
TRO 1

<autonomous transaction start\flag>
<error log to database>

<autonomous transaction finish\flag>

so error log will be stored anyway?

I know about journaling switch (to disable and enable journaling in process), and it also seems working when we map error data to unjournaled database, however, maybe there are other ways? 

  • 0
  • 0
  • 362
  • 4
  • 3

Answers

To keep your logging data even if transaction rolled back, you should have this changes journaled. Because transaction rollback works by the journal. If it happened to be journaled, it will be rolled back anyway.

And you should remember even you disabled journaling for some database, while system journaling working well. Every change which was made during a transaction will be journaled anyway.

So, how to switch off journaling, for this particular data. 

  • CACHETEMP - you can map this data to database CACHETEMP. This database not journaled even if data changed in a transaction. But the problem is, that data here will be available until server will be stopped.
  • Switch journaling temporary off, just only when logging information should be saved. You can do it with command before save, should be placed in %OnBeforeSave method
    DO DISABLE^%NOJRN 
    and return journaling back after saving in method %OnAfterSave
    DO ENABLE^%NOJRN

When you can't use ^%NOJRN (e.g. mirrored database)  you can let 2nd process to move log data from CACHETEMP to production database. Let start 2nd process during Caché start and let test it every 0.1 second if log data in CACHETEMP exists.  

Or maybe use $system.Event, to background logging process. But in this case, if this process is down, nothing will be logged. And I'm not sure about some other possible issues. 

Just a simple suggestion. Wrap the log write into a classmethod and then job the method, any writes in the second job won't be affected by the first jobs rollback.

Elegant approach, but can be costly from perfomance point of view.

Kind of agree, just wondering what type of system has transactions failing so frequently that a speedy logger is needed.

If you log the error with ^%ETN (as in DO BACK^%ETN, or LOG^%ETN, or exceptionobject.Log()), the SETs to the ^ERRORS global are done with the transaction "suspended", so that it does not roll back.  In the future, we will be exposing this functionality for use in applications.  These get recorded in the journal so that they are recovered upon a system crash or restored in a journal restore, but they are omitted from rollback.  As others have said, ^%NOJRN is not the answer because it is ignored for mirrored databases.