数据库事务
在保存订单数据中,涉及到多张表(OrderInfo、OrderGoods、SKU)的数据修改,对这些数据的修改应该是一个整体事务,即要么一起成功,要么一起失败。
Django中对于数据库的事务,默认每执行一句数据库操作,便会自动提交。我们需要在保存订单中自己控制数据库事务的执行流程。
在Django中可以通过django.db.transaction模块提供的atomic来定义一个事务,atomic提供两种用法
整体回滚
装饰器用法
所有的数据库更新操作都会在一个事务中执行,如果事务中任何一个环节出现错误,都会回滚整个事务。
此方案整个view都会在事务之中,所有对数据库的操作都是原子性的。
from django.db import transaction
# open a transaction
@transaction.atomic #装饰器格式
def func_views(request):
do_something()
a = A() #实例化数据库模型
try:
a.save()
except DatabaseError:
pass
with语句用法
事务可以在代码中的任意地方开启,对于事务开启前的数据库操作是必定会执行的,事务开启后的数据库操作一旦出现错误就会回滚。
from django.db import transaction
def func_views(request):
try:
with transaction.atomic(): #上下文格式,可以在python代码的任何位置使用
a = A()
a.save()
#raise DatabaseError #测试用,检测是否能捕捉错误
except DatabaseError: # 自动回滚,不需要任何操作
pass
保存点Savepoint(断点回滚)
在Django中,还提供了保存点的支持,可以在事务中创建保存点来记录数据的特定状态,数据库出现错误时,可以恢复到数据保存点的状态
保存点是事务中的标记,从原理实现上来说是一个类似存储结构的类。可以回滚部分事务,而不是完整事务,同时会保存部分事务。python后端程序可以使用保存点。
一旦打开事务atomic(),就会构建一系列等待提交或回滚的数据库操作。通常,如果发出回滚命令,则会回滚整个事务。保存点则提供了执行细粒度回滚的功能,而不是将执行的完全回滚transaction.rollback()。
工作原理:savepoint通过对返回sid后面的将要执行的数据库操作进行计数,并保存在内置的列表中,当对数据库数据库进行操作时遇到错误而中断,根据sid寻找之前的保存点并回滚数据,并将这个操作从列表中删除。
from django.db import transaction
# 创建保存点
save_id = transaction.savepoint()
# 回滚到保存点
transaction.savepoint_rollback(save_id)
# 提交从保存点到当前状态的所有数据库事务操作
transaction.savepoint_commit(save_id)
# 重置用于生成唯一保存点ID的计数器
clean_savepoints(using = None)
# 这些函数中的每一个都接受一个using参数,该参数是数据库的名称。如果using未提供参数,则# 使用"default"默认数据库。