解决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 strip()函数 介绍
May 24 Python
给Python初学者的一些编程技巧
Apr 03 Python
从零开始学Python第八周:详解网络编程基础(socket)
Dec 14 Python
Python搜索引擎实现原理和方法
Nov 27 Python
Python实现带参数与不带参数的多重继承示例
Jan 30 Python
Pycharm设置去除显示的波浪线方法
Oct 28 Python
python 修改本地网络配置的方法
Aug 14 Python
python单向循环链表原理与实现方法示例
Dec 03 Python
Python如何获取Win7,Win10系统缩放大小
Jan 10 Python
Python实现自动访问网页的例子
Feb 21 Python
Python计算矩阵的和积的实例详解
Sep 10 Python
python图片合成的示例
Nov 09 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
曾在DC漫画界反派角色扮演的演员,谁才是你心目中的小丑之王?
2020/04/09 欧美动漫
php中的curl使用入门教程和常见用法实例
2014/04/10 PHP
PHP文件操作实例总结【文件上传、下载、分页】
2018/12/08 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
[HTML/CSS/Javascript]WWTJS
2007/09/25 Javascript
调用HttpHanlder的几种返回方式小结
2013/12/20 Javascript
使用jQuery时Form表单元素ID和name命名大忌
2014/03/06 Javascript
angular.foreach 循环方法使用指南
2015/01/06 Javascript
深入理解JavaScript系列(39):设计模式之适配器模式详解
2015/03/04 Javascript
JS中的==运算: [''] == false —>true
2016/07/24 Javascript
Express + Session 实现登录验证功能
2017/09/08 Javascript
canvas+gif.js打造自己的数字雨头像的示例代码
2017/10/26 Javascript
JavaScript函数式编程(Functional Programming)组合函数(Composition)用法分析
2019/05/22 Javascript
vue-element-admin 菜单标签失效的解决方式
2019/11/12 Javascript
详解vue中在父组件点击按钮触发子组件的事件
2020/11/13 Javascript
[32:56]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.11
2020/12/16 DOTA
[42:48]完美世界DOTA2联赛PWL S3 Magma vs INK ICE 第二场 12.11
2020/12/16 DOTA
Python环境变量设置方法
2016/08/28 Python
fastcgi文件读取漏洞之python扫描脚本
2017/04/23 Python
详解Django 中是否使用时区的区别
2018/06/14 Python
python脚本当作Linux中的服务启动实现方法
2019/06/28 Python
Django多进程滚动日志问题解决方案
2019/12/17 Python
Django查询优化及ajax编码格式原理解析
2020/03/25 Python
Python实现Word表格转成Excel表格的示例代码
2020/04/16 Python
详解用Python调用百度地图正/逆地理编码API
2020/07/02 Python
python基本算法之实现归并排序(Merge sort)
2020/09/01 Python
python如何调用百度识图api
2020/09/29 Python
工作自荐信
2013/12/11 职场文书
网上开商店的创业计划书
2014/01/19 职场文书
军训口号
2014/06/13 职场文书
应届毕业生求职信范文
2014/07/07 职场文书
2014国庆65周年领导讲话稿(3篇)
2014/09/21 职场文书
2015年信访维稳工作总结
2015/04/07 职场文书
Go语言空白表示符_的实例用法
2021/07/04 Golang
公历12个月名称的由来
2022/04/12 杂记
让JavaScript代码更加精简的方法技巧
2022/06/01 Javascript