Question Sergey Pavlov · Aug 25, 2017

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>

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? 

Comments

Dmitry Maslennikov · Aug 25, 2017

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
0
Martin Fukátko  Aug 25, 2017 to Dmitry Maslennikov

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.  

0
Dmitry Maslennikov  Aug 25, 2017 to Martin Fukátko

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. 

0
Sean Connelly · Aug 25, 2017

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.

0
Evgeny Shvarov  Aug 25, 2017 to Sean Connelly

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

0
Sean Connelly  Aug 25, 2017 to Evgeny Shvarov

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

0
Ray Fucillo · Aug 28, 2017

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.

0