Atomic transaction

I need to develop a routine in python using Django, where I will have an atomic block that will remain in it some operations in the database and among them, the creation of a specific record in a certain table in the database that, if any error occurs in this routine, I want to rollback everything but the creation of this specific record.

Example:

def do_something_2():
do_something_1()

def do_something_1():
with transaction.atomic():
obj_c.save()

def_test function:

with transaction.atomic():

   obj_a.save()
   obj_b.save()
   do_something_2()   
   obj_d.save()
   raise #At this point, when raising the exception I want to rollback only the register a, b, d. The c register i want commit in the database.

Obs.: I can’t include an exception handling inside function_test to handle the exception and work with save points or something like that, because this example is very simplified. And in practice what will happen is that inside the test_function I will call several chained routines that will create this c record inside it and, when the flow returns to the external method (test_function) and there is any increase, I need to rollback everything but the register c.

What I want to implement would be the same idea of ​​having an autonomous oracle transaction. Where I have a transaction and within it I can commit a specific item without having influence on the main transaction.

I tried to use some methods related to the djando transaction and I couldn’t get the expected result.

If I’m understanding you correctly, you can’t do this from within the single thread of your process.

To recreate what Oracle does with its autonomous transactions, you’d have to make an external procedural call to perform that operation in complete isolation from your primary thread.

For example, you could create a view to create c, then use the requests module to invoke that view allowing c to be created independently of the thread creating a, b, and d.

Or, depending upon how frequently c needs to be created, you could use something like celery to create c in an external process.

The first creates fewer dependencies if you’re not already using celery and makes it easier to directly return results. The second reduces or eliminates the overhead of an additional http request.

1 Like

Hello,

Thank you so much! Your solution about “Celery” is working and I got to implent it and obtain the result I was especting.

The only thing I need to discorver is how can i see the logs of execution of my shared task. Because I dont’t find wich table of my database are they logged.

In the django_db_logger_statuslog there isn’t log any has been registered. So, can you give me any tip for fix it?

My code is like this:

from celery import shared_task
from celery.utils.log import get_task_logger

logger = get_task_logger(name)

@shared_task(name=“test_100”)
def test_100():
print(“oiuasdf”)
logger.info(“OIOIOIOIOIOIOI”)
return 3

What does your logging configuration look like in your settings?
(Or are you configuring the loggers elsewhere?)

Side note: In the future, please do not post images of code. Copy/paste the code into the body of your message.

When you’re posting code, surround it with lines of three backtick - ` characters. This means you’ll have a line of ```, then your code (template, traceback, etc), then another line of ```.

I don’t see where you have a logger defined for your celery tasks. The default is to only log to the console.

Sorry! In the next time I will send just the code.

I don’t have “Celery” log configured in the my project. Probably the log it’s being printed in the console and i can’t view it. If I want save these logs in database, how could I do? For example in the django_db_logger_statuslog.

You would need to configure a logger (in loggers matching the name of the logger declared in your code), referencing either your existing db_log handler, or a different handler for how you want it logged.

It appears you are using the django-db-logger package, so you might want to look at it to see what options you may have available.

Ok, I’ll take a look in this.

So, that’s it! Thank so much you for all your help.