Jason McDonough
Jason McDonough

Reputation: 147

Django nested Transaction.atomic not rolled back

I have two logically connected instance in two different data bases. I want them both to be saved or rollbacked. But if I raise an exception in an outer block - nested Transaction.atomic will not rollback, but why?

From documentation:

atomic blocks can be nested. In this case, when an inner block completes successfully, its effects can still be rolled back if an exception is raised in the outer block at a later point.

def __commit_to_db(self, mesure, mdm_mesure):
    try:
        with transaction.atomic():
            mesure.save()
            with transaction.atomic(using='mdm'):
                mdm_mesure.save()
            raise Exception('oops')
    except (KeyboardInterrupt, SystemExit):
        raise
    except BaseException as error:
        MainLoger.log_error(error)
    return

Upvotes: 2

Views: 1288

Answers (1)

Kevin Christopher Henry
Kevin Christopher Henry

Reputation: 48982

Transactions are a database-level feature. So although you're nesting the Python code, each database is actually getting its own transaction independent of the other. There are no nested transactions that span databases in Django.

You'll have to restructure your code in some way. For example, putting your code inside both atomic() blocks would work:

try:
    with transaction.atomic():
        with transaction.atomic(using='mdm'):
            mesure.save()
            mdm_mesure.save()

            # neither transaction will commit
            raise Exception('oops')
except Exception:
    pass

Upvotes: 1

Related Questions