Solve the pit that Django transaction stepped on in transaction management
- 2021-11-01 04:04:53
Transaction is the implementation of django for database atomicity operation at python level.
Simply put, the code block wrapped by transaction. atomic () only performs commit at the database level after the code block is successfully completed. In the actual development, I encountered some problems.
1. commit operations for the database are not performed within an transaction transaction
Unless manual commit
The most basic functions of transaction.
The celery asynchronous task is started at the current transaction, and uncommitted changes cannot be obtained.
def example_view(request): with transaction.atomic(): change_obj() # Modify object variables obj.save() async_task.delay(obj.id) def async_task(obj_id): obj = Model.objects.get(pk=obj_id) read_the_obj() # Read object information
In using transaction, Model. save () does not do commit, so if asynchronous tasks are set in transaction and get () is used to query the database, no object changes in transactions will be seen. This is also the transaction isolation level to realize "repeatable reading", that is, multiple queries in the same transaction should keep the results unchanged.
2. transaction manages transactions only for database layer operations
Transaction management that cannot be understood as python operation
The code is as follows:
def example_view(request): tag = False with transaction.atomic(): tag = True change_obj() # Modify object variables obj.save() raise DataError print("tag = ",tag)
tag = True # Output content
Even if DataError occurs in the transaction code block, the transaction rollback is only a database-level rollback, and the operation against python is still completed.
Even operations on Model. Object will exist in variables.
def example_view(request): obj.changed = False with transaction.atomic(): obj.changed = True change_obj() # Modify other variables of the object obj.save() raise DataError print("obj.changed = ",obj.changed)
obj.changed = True # Output content
A rollback with an Dataerror exception only operates at the database level, so it is not possible to judge whether the transaction completed correctly based on the attribute value of model object.
In addition, although Django abstracts the database level with ORM, it should be clearly realized that the model object we operate is essentially different from the database content, and DJANGO only performs database operations during query and submission.
Supplement: How to use Django transaction transaction. atomic ()
Look at the code ~
from django.shortcuts import render from django.http import HttpResponse from django.views.generic import View from django.db import transaction # Import transaction # Class view ( Affairs ,@transaction.atomic Decorator ) class MyView(View): @transaction.atomic # transaction.atomic The decorator ensures that all database operations in this function are in the 1 In a transaction. def post(self, request): # Database operation 1 . . . # Database operation 2 . . . return HttpResponse('ok') # Class view ( Affairs , Use of Savepoint ) class MyView2(View): @transaction.atomic def post(self, request): # Setting Transaction Savepoint s1 = transaction.savepoint() # You can set multiple save points # Database operations. . . # Transaction rollback ( If an exception occurs , Roll back the transaction ) transaction.savepoint_rollback(s1) # You can roll back to the specified save point # Commit transaction ( If there is no exception , Commit a transaction ) transaction.savepoint_commit(s1) # Return a reply return HttpResponse('ok')