解决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的PIL模块来进行图片对比
Feb 18 Python
python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)
May 25 Python
对python 数据处理中的LabelEncoder 和 OneHotEncoder详解
Jul 11 Python
利用Python+阿里云实现DDNS动态域名解析的方法
Apr 01 Python
使用Python做定时任务及时了解互联网动态
May 15 Python
Python Django Cookie 简单用法解析
Aug 13 Python
pandas实现将日期转换成timestamp
Dec 07 Python
python通过文本在一个图中画多条线的实例
Feb 21 Python
Python中使用socks5设置全局代理的方法示例
Apr 15 Python
python链表类中获取元素实例方法
Feb 23 Python
python爬取股票最新数据并用excel绘制树状图的示例
Mar 01 Python
Python Pandas常用函数方法总结
Jun 15 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
杏林同学录(七)
2006/10/09 PHP
浅谈discuz密码加密的方式
2014/05/22 PHP
PHPMailer发送HTML内容、带附件的邮件实例
2014/07/01 PHP
微信公众号开发之微信公共平台消息回复类实例
2014/11/14 PHP
学习php设计模式 php实现备忘录模式(Memento)
2015/12/09 PHP
ThinkPHP项目分组配置方法分析
2016/03/23 PHP
ThinkPHP框架整合微信支付之JSAPI模式图文详解
2019/04/09 PHP
Cookie 注入是怎样产生的
2009/04/08 Javascript
JavaScript 数组详解
2013/10/10 Javascript
JavaScript关闭当前页面(窗口)不带任何提示
2014/03/26 Javascript
javascript实现校验文件上传控件实例
2015/04/20 Javascript
第一次接触神奇的Bootstrap导航条
2016/08/09 Javascript
解决wx.onMenuShareTimeline出现的问题
2016/08/16 Javascript
JS实现漂亮的时间选择框效果
2016/08/20 Javascript
详解angularJs中自定义directive的数据交互
2017/01/13 Javascript
微信小程序page的生命周期和音频播放及监听实例详解
2017/04/07 Javascript
js Date()日期函数浏览器兼容问题解决方法
2017/09/12 Javascript
bootstrap实现二级下拉菜单效果
2017/11/23 Javascript
实现jquery放大镜的两种方法
2018/02/22 jQuery
vue观察模式浅析
2018/09/25 Javascript
JS实现处理时间,年月日,星期的公共方法示例
2019/05/31 Javascript
Vue自定义render统一项目组弹框功能
2020/06/07 Javascript
JS highcharts实现动态曲线代码示例
2020/10/16 Javascript
如何正确解决VuePress本地访问出现资源报错404的问题
2020/12/03 Vue.js
Python采用socket模拟TCP通讯的实现方法
2014/11/19 Python
Python中的高级数据结构详解
2015/03/27 Python
python中redis的安装和使用
2016/12/04 Python
cmd运行python文件时对结果进行保存的方法
2018/05/16 Python
Python实用技巧之利用元组代替字典并为元组元素命名
2018/07/11 Python
Python DataFrame.groupby()聚合函数,分组级运算
2018/09/18 Python
详解pandas中iloc, loc和ix的区别和联系
2020/03/09 Python
Docker如何部署Python项目的实现详解
2020/10/26 Python
存储过程和函数的区别
2013/05/28 面试题
读书心得体会
2013/12/28 职场文书
上班离岗检讨书
2014/01/27 职场文书
Win11 BitLocker 驱动器加密
2022/04/19 数码科技