grails-audit-logging-plugin
grails-audit-logging-plugin copied to clipboard
GPAUDITLOGGING-4: Audit Logging Causes Rollback To Fail
Original Reporter: bdrhoa Environment: MySQL (Innodb), Grails 1.3.7 Migrated From: http://jira.grails.org/browse/GPAUDITLOGGING-4
If auditable = true then the insert into the audit log ends up creating a commit when a roleback is supposed to take place.
Example scenario:
Customer has a Person:owner Person hasMany Authorities Authority hasMany People
Given a Person who has Authority records and is in use as an owner of a Customer. In a transaction:
- Delete his Authority records
- Try to delete the Person record
This will cause a Referential Integrity Constraint error and should rollback the delete to the Authority records. However, the insert into the audit log and a commit get's sent to the DB, before the rollback from the error.
See the SQL log that illustrates the problem.
Setting transactional = true in config.groovy has no effect. The only current solution is to use static auditable = [handlersOnly:true].
robertoschwald said:
Maybe we should switch to withNewTransaction to decouple audit logging from the main transaction.
bdrhoa said:
If I understand what you're saying correctly, then we would in fact have two separate transactions, one for the application transaction and one to create the audit record. If that's the case, then wouldn't a rollback of the application transaction end up with the original transaction left in the log? That would be OK as long as the rollback created an offsetting log entry too.
longwa said:
The 'transactional' flag is a bit confusing to me. I would think you want one of two behaviors:
- Audit logging becomes part of any current transaction so that the logging and the db operation are atomic and either succeed or fail together (this should be the default IMO).
- Audit logging is always in a new transaction and is persisted regardless of the outcome of the enclosing transaction.
Right now, the code doesn't handle the second case and even the first case is a bit dicey.
For example, the actual save() of the audit log can be inside of a withTransaction() if using transactional= true, but since it's only wrapping the individual save(), it's not really doing much.
At a minimum, I would think ALL of the audit rows for a single operation should be within a transaction together so you don't ever risk getting a partial log (especially true when verboseLog is enabled).
is it fixed in new 1.1.0 release ?