Managing transactions using multiple databases

357 views
Skip to first unread message

Leandro Boscariol

unread,
Jul 6, 2013, 8:54:34 AM7/6/13
to django...@googlegroups.com
Hello,

During the design of a project, I came across a situation where I will have 2 databases.

Dealing with transactions even when having multiple databases is also trivial, simply select which one the transaction is about.

At a given point, I'll have to interact with both databases in the same view.
Consider the snippet below as an example (not tested, nor this is what I intend to do):

@transaction.commit_manually()  # using='db1' or using='db2' or none??
def my_view(request):
    try:
        obj1 = MyObject1()
        obj1.data = request.POST.get('data')
        obj1.save(using='db1')
        obj2 = MyObject2()
        obj2.obj1_id = obj1id
        obj2.save(using='db2')
    except:
        transaction.rollback()
    else:
        transaction.commit()
    ...


I didn't find any mention in the docs or in this list related to this, so here is my question:

How can I do a transaction management in both databases at the same time? Is that even possible?


Thanks in advance for your help.
Leandro.

Christophe Pettus

unread,
Jul 6, 2013, 9:41:11 AM7/6/13
to django...@googlegroups.com

On Jul 6, 2013, at 2:54 PM, Leandro Boscariol wrote:

> How can I do a transaction management in both databases at the same time? Is that even possible?

You can certainly nest the transaction context managers (atomic() in 1.6+, or you can use xact() in 1.5 and earlier):

with xact(using=DATABASE1):
with xact(using=DATABASE2):
things

If an exception occurs, it will rollback both; if it exits normally, it will commit both. Note that this isn't true two-phase commit; it's perfectly possible for the inner transaction to successfully commit but the outer one to fail. If you want proper two-phase commit, you'll (at the moment, at least) have to roll your own.

--
-- Christophe Pettus
x...@thebuild.com

Leandro Boscariol

unread,
Jul 6, 2013, 2:58:56 PM7/6/13
to django...@googlegroups.com
Well, even though without true two-phase commit, for now that will do, thanks.

And also thanks for mentioning xact, I wasn't aware of that!

Cheers,
Leandro

Christophe Pettus

unread,
Jul 6, 2013, 3:44:20 PM7/6/13
to django...@googlegroups.com

On Jul 6, 2013, at 8:58 PM, Leandro Boscariol wrote:
> And also thanks for mentioning xact, I wasn't aware of that!

Full disclosure: I wrote it. :) In 1.6, the new atomic() decorator / context manager is the way to go, but xact() works fine for now!

Leandro Boscariol

unread,
Jul 8, 2013, 4:12:10 PM7/8/13
to django...@googlegroups.com
Amazing work Christophe, congrats!
Lot's of new cool stuff being added to 1.6, looking forward to it.

Regarding the nested xact context managers, let's say something that I don't like happened and I want to abort everything:

with xact(using=db1):
    with xact(using=db2):
        obj1 = Ob1.save(using=db1)
        obj2 = Obj2.save(using=db2)
        if not_cool:
            raise Rollback

I'll raise Rollback since this is the way to force a rollback, as described in the README.
But, this will roll back only whatever happened in the inner context manager, thus obj1 will still exist, right?

Is there a way to make the Rollback reach the outer xact?
You wrote in a previous email that an exception will abort both, so something like this should be the solution? (I have not tested):

try:
    with xact(using=db1):
        with xact(using=db2):
            obj1 = Ob1.save(using=db1)
            obj2 = Obj2.save(using=db2)
            if not_cool:
                raise Exception
except Exception:
    return False
return True


Cheers,
Leandro



--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/WJUIVH2abjo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
For more options, visit https://groups.google.com/groups/opt_out.



Reply all
Reply to author
Forward
0 new messages