数据库事务
这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
Django 提供多种方式控制数据库事务。
在调用试图方法前,Django 先生成一个事务。如果响应能正常生成,Django 会提交该事务。而如果视图出现异常,Django 则会回滚该事务。
你可以在你的视图代码中使用还原点执行子事务,一般会使用 atomic()
上下文管理器。但是,在视图结束时,要么所有的更改都被提交,要么所有的更改都不被提交。
注意,只有视图被限制在事务中执行。中间件在事务之外运行,同理,渲染模板响应也是在事务之外运行的。
1、Django中使⽤事务说明
在保存订单数据中,涉及到多张表的数据修改,对这些数据的修改应该是一个整体事务,即要么一起成功,要么一起失败。
Django中对于数据库的事务,默认每执行一句数据库操作,便会自动提交。我们需要在保存订单中自己控制数据库事务的执行流程。
在Django中可以通过django.db.transaction
模块提供的atomic
来定义一个事务,atomic
提供两种用法
-
装饰器用法
from django.db import transaction @transaction.atomic # 一个出错就报错 def viewfunc(request): # 这些代码会在一个事务中执行 ... 复制代码
-
with语句用法
from django.db import transaction def viewfunc(request): # 这部分代码不在事务中,会被Django自动提交 ... with transaction.atomic(): # 这部分代码会在事务中执行 ... 复制代码
在Django中,还提供了保存点的支持,可以在事务中创建保存点来记录数据的特定状态,数据库出现错误时,可以恢复到数据保存点的状态
from django.db import transaction
# 创建保存点
save_id = transaction.savepoint()
# 回滚到保存点
transaction.savepoint_rollback(save_id)
# 提交从保存点到当前状态的所有数据库事务操作
transaction.savepoint_commit(save_id)
复制代码
2、显式控制事务
atomic
(using=None, savepoint=True)¶
原子性是数据库事务的定义属性。 atomic
允许创建代码块来保证数据库的原子性。如果代码块成功创建,这个变动会提交到数据库。如果有异常,变动会回滚。
atomic
块可以嵌套。在这个例子里,当内部块成功完成时,如果在稍后外部块里引发了异常,则仍可回滚到最初效果。
atomic
既可用作 decorator
方法一:
from django.db import transaction
@transaction.atomic
def viewfunc(request):
do_stuff()
复制代码
方法二:
from django.db import transaction
def viewfunc(request):
do_stuff()
with transaction.atomic():
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()
复制代码
提交后
需要执行与当前数据库事务相关的操作,但前提是事务成功提交。例子可能包含 Celery任务,邮件提醒或缓存失效。
Django提供on_commit()函数来注册成功提交事务后应执行的回调函数:
on_commit
(func, using=None)
将任意函数(无参数)传递给 on_commit()
from django.db import transaction
def do_something():
pass # send a mail, invalidate a cache, fire off a Celery task, etc.
transaction.on_commit(do_something)
复制代码
你也可以使用 lambda:: 包装函数
transaction.on_commit(lambda: some_celery_task.delay('arg1'))
复制代码
注意:事务提交成功后,才走异步任务
近期评论