使用背景:

比如在生成订单时,需要一次性生成多条数据记录或者一次操作多个orm模型,而这些操作都会有可能在中途发生意外,因此需要用事物

管理数据库事务

Django 默认的事务行为

Django 默认的事务行为是自动提交。除非事务正在执行,每个查询将会马上自动提交到数据库。

Django 自动使用事务或还原点,以确保需多次查询的 ORM 操作的一致性,特别是 delete() 和 update() 操作。

由于性能原因,Django 的 TestCase 类同样将每个测试用事务封装起来

是视图函数中使用事务管理

第一步需要在setting.py更改DataBase连接,将ATOMIC_REQUESTS设置为 True

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

警告:

虽然这种简洁的事务模型很吸引人,但在流量增加时,也会降低效率。为每个视图打开一个事务都会带来一些开销。对性能的影响程度取决于应用执行的查询语句和数据库处理锁的能力。

不建议在流式响应在视图函数使用事务管理

原因:

当视图返回一个 StreamingHttpResponse 时,获取该响应的内容总会执行代码,生成内容。由于早就返回了该视图,某些代码会在事务外执行。

一般来说,不建议在生成流式响应时写入数据库,因为在开始发送响应后,就没有能有效处理错误的方法了。

示例:

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()

直接在函数中使用事务管理

使用装饰器代码示例:

from django.db import transaction

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

使用上下文管理

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()

异常处理

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()

在这个例子里,虽然 generate_relationships() 会通过破坏完整性约束导致数据库错误,但你可以 add_children() 中执行查找,来自 create_parent() 的变化也会在这里,并且绑定到相同的事务。

注意,任何试图在 generate_relationships() 中执行的操作在 handle_exception() 被调用的时候也会安全的回滚,因此异常处理也会在必要的时候在数据库上操作。

异常处理注意:

当存在 atomic 块时, Django 查看它是否正常退出或存在异常来决定是提交还是正常回滚。如果你在 atomic 内部捕捉并且处理异常,你可以对 Django 隐藏问题代码。这会导致一些意外的行为。

这主要是 DatabaseError 和它的子类的一个问题(比如 IntegrityError )。出现这样的错误之后,事务会奔溃,并且 Django 将在 atomic 块的末尾执行回滚。如果你打算在回滚发生的时候运行数据库查询,Django 将引发 TransactionManagementError 错误。当 ORM 相关的信号处理程序引发异常时,你也可能遇到这个问题。

捕捉数据库错误的正确的方法是像上方所示那样围绕 atomic 块。如有需要,为此目的可以添加额外的 atomic 块。这个模式有别的优势:如果异常发生,它会明确界定哪些操作将回滚。

如果捕获由原始SQL查询引发的异常,那么Django的行为是未指定的,并且依赖于数据库。

参考文章:

django数据库事务

本文地址: http://chenxm.cc/article/1225.html
版权声明: 本文为原创文章,版权归  陈新明  所有,欢迎分享本文,转载请保留出处!
上一篇: mysql 清空指定数据库下指定表的数据且保留表结构
下一篇: word读取图片,并将图片转换成链接
发表评论

还没有留言,还不快点抢沙发?