2

I've inherited some complex logic that does several different DML actions within the same (fairly long) method and if there are failures I need to revert everything that's been previously done. The existing solution involved setting a Database.savepoint at the top of the method, and doing Database.rollback() in the event of failure.

The problem is that while reading through the documentation around these functions, I realized that there's no description of (or ability to define) the scope of the DB snapshot that's taken, and in fact, all available information seems to indicate that it's a global snapshot of the DB. Given that we operate in a multi-tenant environment, this leads me to worry that when you rollback, you would potentially be wiping out unrelated DB changes made by another user during the same window of time.

Well, now I've inherited this tract of code that makes liberal use of the rollback, but with such a sensitive mixture of insert, update, and delete operations going on here, I don't think I have any alternative method of cleanup after failure. So I guess my question is whether anybody out there can confirm or deny this destructive side-effect, preferably with some clear documentation?

PS: I reached out to my Technical Evangelist at the time to confirm this risk, and to my surprise he had never heard anybody bring up such a concern before. Basically, he said that he wasn't certain, but that my concern sounded like a very likely outcome (and in fact the outcome that he would expect, given some thought) and that I should avoid all use of this call.

5
8

I wish I had some very clear documentation, but to be honest, I don't. I assume you found the small amount of documentation on savepoints and rollbacks here: https://developer.salesforce.com/docs/atlas.en-us.integration_patterns_and_practices.meta/apexcode/langCon_apex_transaction_control.htm

Notice the title is "Transaction Control" and that savepoints can't be referenced outside of the transaction they were created in. If you have any database experience, you understand that a typical savepoint is really just a line in the set of instructions for the database to execute. It looks something like this for setting a savepoint and updating a single field:

Begin TRANSACTION1
DATABASE SAVE S1
Change Account.Name Row 12345 FROM 'Acme' TO 'Acme2'
End TRANSACTION1

Two users will not share the above instruction file because a transaction is on a PER USER basis. When a rollback is issued, it must be issued in the transaction is was requested and instead of there actually being a savepoint, the database just goes back up the file until and executes the instructions in the opposite order. Example:

User 1

1. BEGIN USER1
3. DATABASE SAVE S1
4. Change Account.Name Row 12345 FROM 'Acme' TO 'Acme2'
7. Change Account.Name Row 12346 FROM 'Global' TO 'Global2'
8. DATABASE ROLLBACK S1
9. END USER1

User 2

2. BEGIN USER2
5. Change Account.Name Row 98765 FROM 'Universal Containers' TO 'Acme2'
6. END USER2

If we assume both user 1 and 2 begin at the same time and the changes execute in the order I've numbered, only the individual commands in USER1's file are saved. When step 8 hits and the Database receives a Rollback, it simply walks up the file and reverses its changes for that user until it reaches the savepoint.

If someone can provide some good documentation on this, that would help. I hope this wasn't too confusing.

2
  • 2
    That makes solid sense, and is certainly how I hope it actually works, but yeah, what I really want here is a piece of official documentation that explicitly says this is safe... – RenegadeCoder Jan 13 '15 at 20:19
  • 1
    @BradleyDulaune - GREAT answer! – Eric Jan 13 '15 at 20:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.