解决Django transaction进行事务管理踩过的坑


Posted in Python onApril 24, 2021

概要

Transaction是django进行数据库原子性操作在python层面上的实现。

简单来说, 被transaction.atomic()包裹的代码块只在代码块顺利完成后进行数据库层面的commit。实际开发当中,遇到了一些问题。

1. transaction事务内不执行数据库的commit操作

除非手动commit

transaction最基本的功能。

代码场景:

在事务当前启动celery异步任务, 无法获取未提交的改动。

def example_view(request):
    with transaction.atomic():
        change_obj() # 修改对象变量
        obj.save()
        async_task.delay(obj.id)
def async_task(obj_id):
    obj = Model.objects.get(pk=obj_id)
    read_the_obj() # 读取对象信息

在使用transaction当中, Model.save()都不做commit,因此如果在transaction当中设置异步任务,使用get()查询数据库,将看不到对象在事务当中的改变.这也是实现”可重复读”的事务隔离级别,即同一个事务里面的多次查询都应该保持结果不变。

2.transaction只对数据库层的操作进行事务管理

不能理解为python操作的事务管理

代码如下:

def example_view(request):
    tag = False
    with transaction.atomic():
        tag = True
        change_obj() # 修改对象变量
        obj.save()
        raise DataError
    print("tag = ",tag)
tag = True #输出内容

即使事务代码块发生了DataError,事务回滚,也仅是数据库层面的回滚,针对python的操作依然已完成。

甚至是对Model.Object进行的操作会也会存在变量当中。

如:

def example_view(request):
    obj.changed = False
    with transaction.atomic():
        obj.changed = True
        change_obj() # 修改对象其他变量
        obj.save()
        raise DataError
    print("obj.changed = ",obj.changed)
obj.changed = True #输出内容

发生Dataerror异常的回滚仅在数据库层面操作,因此不可以根据model object的属性值判断是否正确完成了事务。

另外,虽然Django对数据库层面以ORM完成了很具体的抽象,但应该要清楚地意识到我们操作的model object和数据库内容本质不同,DJANGO只在查询和提交时进行数据库操作。

补充:Django 事务transaction.atomic()的使用方法

看代码吧~

from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import View
from django.db import transaction   # 导入事务 
 
# 类视图 (事务,@transaction.atomic装饰器)
class MyView(View): 
    @transaction.atomic
    # transaction.atomic装饰器可以保证该函数中所有的数据库操作都在一个事务中。
    def post(self, request):
 
        # 数据库操作1。。。
        # 数据库操作2。。。        
        return HttpResponse('ok') 
 
# 类视图 (事务,保存点的使用)
class MyView2(View):
    @transaction.atomic
    def post(self, request): 
        # 设置事务保存点
        s1 = transaction.savepoint()   # 可以设置多个保存点
 
        # 数据库操作。。。
 
        # 事务回滚 (如果发生异常,就回滚事务)
        transaction.savepoint_rollback(s1)  # 可以回滚到指定的保存点
 
        # 提交事务 (如果没有异常,就提交事务)
        transaction.savepoint_commit(s1)
 
        # 返回应答
        return HttpResponse('ok')

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Python 相关文章推荐
正确理解python中的关键字“with”与上下文管理器
Apr 21 Python
python的多重继承的理解
Aug 06 Python
Python安装图文教程 Pycharm安装教程
Mar 27 Python
pandas数据预处理之dataframe的groupby操作方法
Apr 13 Python
选择Python写网络爬虫的优势和理由
Jul 07 Python
python多线程使用方法实例详解
Dec 30 Python
django处理select下拉表单实例(从model到前端到post到form)
Mar 13 Python
python matplotlib模块基本图形绘制方法小结【直线,曲线,直方图,饼图等】
Apr 26 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
May 13 Python
python中rb含义理解
Jun 18 Python
python实现批处理文件
Jul 28 Python
浅谈Python列表嵌套字典转化的问题
Apr 07 Python
pdf论文中python画的图Type 3 fonts字体不兼容的解决方案
Apr 24 #Python
Python使用UDP实现720p视频传输的操作
python通配符之glob模块的使用详解
Apr 24 #Python
Django debug为True时,css加载失败的解决方案
Apr 24 #Python
python 模块重载的五种方法
Apr 24 #Python
写一个Python脚本自动爬取Bilibili小视频
python实现图片批量压缩
Apr 24 #Python
You might like
QueryPath PHP 中的jQuery
2010/04/11 PHP
PHP+Mysql+jQuery实现发布微博程序 php篇
2015/10/15 PHP
使用PHP如何实现高效安全的ftp服务器(二)
2015/12/30 PHP
php使用pclzip类实现文件压缩的方法(附pclzip类下载地址)
2016/04/30 PHP
关于php中的json_encode()和json_decode()函数的一些说明
2016/11/20 PHP
YII框架批量插入数据的方法
2017/03/18 PHP
浅谈PHP中的面向对象OOP中的魔术方法
2017/06/12 PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
2020/02/16 PHP
统一接口:为FireFox添加IE的方法和属性的js代码
2007/03/25 Javascript
让你的CSS像Jquery一样做筛选的实现方法
2011/07/10 Javascript
根据经纬度计算地球上两点之间的距离js实现代码
2013/03/05 Javascript
js浮动图片的动态效果
2013/07/10 Javascript
Javascript排序算法之合并排序(归并排序)的2个例子
2014/04/04 Javascript
JavaScript italics方法入门实例(把字符串显示为斜体)
2014/10/17 Javascript
js输出数据精确到小数点后n位代码
2016/07/02 Javascript
AngularJS 基础ng-class-even指令用法
2016/08/01 Javascript
浅谈vuex 闲置状态重置方案
2018/01/04 Javascript
浅谈React之状态(State)
2018/09/19 Javascript
浅谈微信页面入口文件被缓存解决方案
2018/09/29 Javascript
vue路由跳转传参数的方法
2019/05/06 Javascript
json解析大全 双引号、键值对不在一起的情况
2019/12/06 Javascript
jquery实现吸顶导航效果
2020/01/08 jQuery
[42:52]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
Django实现图片文字同时提交的方法
2015/05/26 Python
利用django如何解析用户上传的excel文件
2017/07/24 Python
Python Django基础二之URL路由系统
2019/07/18 Python
python创建ArcGIS shape文件的实现
2019/12/06 Python
Python 实现将numpy中的nan和inf,nan替换成对应的均值
2020/06/08 Python
Python基础教程(一)——Windows搭建开发Python开发环境
2020/07/20 Python
python pymysql库的常用操作
2020/10/16 Python
CSS3实现菜单悬停效果
2020/11/17 HTML / CSS
Holland & Barrett爱尔兰:英国领先的健康零售商
2019/03/31 全球购物
学生实习自我鉴定
2013/10/11 职场文书
书法大赛策划方案
2014/06/04 职场文书
家属答谢词
2015/01/05 职场文书
2016大学生国家助学贷款承诺书
2016/03/25 职场文书