Django uses transcation to handle database transaction management

created at 07-15-2021 views: 1

scenes to be used

For example, when generating an order, you need to generate multiple data records at once or operate multiple orm models at a time, and these operations may cause accidents in the middle, so you need to use things

Manage database transactions

Django default transaction behavior

Django's default transaction behavior is automatic commit. Unless the transaction is being executed, each query will be automatically submitted to the database immediately.

Django automatically uses transactions or restore points to ensure the consistency of ORM operations that require multiple queries, especially delete() and update() operations.

For performance reasons, Django's TestCase class also encapsulates each test transaction

Use transaction management in view functions

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
        'ATOMIC_REQUESTS':True,
    }
}

warning

Although this simple transaction model is very attractive, it will also reduce efficiency when traffic increases. Opening a transaction for each view brings some overhead. The degree of impact on performance depends on the query statements executed by the application and the ability of the database to handle locks.

It is not recommended to use transaction management in view functions in streaming responses.

reason

When the view returns a StreamingHttpResponse, getting the content of the response will always execute the code to generate the content. Since the view was returned long ago, some code will be executed outside of the transaction.

Generally speaking, it is not recommended to write to the database when generating a streaming response, because there is no effective way to handle errors after you start sending the response.

Example

from django.db import transaction

@transaction.non_atomic_requests
def my_view(request):
    do_stuff()

@transaction.non_atomic_requests(using='other')
def my_other_view(request):
    do_stuff_on_the_other_database()

Use transaction management directly in the function

Example of using decorator code

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

Use context management

from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()

Exception handling

from django.db import IntegrityError, transaction

@transaction.atomic
def viewfunc(request):
    create_parent()

    try:
        with transaction.atomic():
            generate_relationships()
    except IntegrityError:
        handle_exception()

    add_children()

In this example, although generate_relationships() will cause database errors by breaking integrity constraints, you can perform a lookup in add_children(), and the changes from create_parent() will also be here and bound to the same transaction.

Note that any operation attempted to perform in generate_relationships() will be safely rolled back when handle_exception() is called, so exception handling will also operate on the database when necessary.

Exception handling note:

When there is an atomic block, Django checks whether it exits normally or if there is an exception to decide whether to commit or rollback normally. If you catch and handle exceptions inside atomic, you can hide the problem code from Django. This can cause some unexpected behavior.

This is mainly a problem with DatabaseError and its subclasses (such as IntegrityError ). After such an error, the transaction will crash, and Django will perform a rollback at the end of the atomic block. If you plan to run a database query when the rollback occurs, Django will raise a TransactionManagementError. You may also encounter this problem when the ORM-related signal handler raises an exception.

The correct way to catch database errors is to surround the atomic block as shown above. If necessary, additional atomic blocks can be added for this purpose. This model has other advantages: if an exception occurs, it will clearly define which operations will be rolled back.

If an exception raised by a raw SQL query is caught, then Django's behavior is unspecified and depends on the database.

Please log in to leave a comment.