Django 事务操作
如何在Django中进行事务操作
案例:
客户A要给客户B转一笔钱,这个在数据库中需要进行两步:
1.客户A减钱
2.客户B加钱
如果在第一步结束后,服务器出现异常,停下了,第二步没有进行,如果数据库使用了事务操作,真的出现异常的时候,前面的操作会进行回滚。
简单的说就是:要么全部执行成功,要么一个都不执行。
这个回滚的操作就叫做数据库的原子性操作。
但是,这是在MySQL数据库中,而我们在Django的ORM中如何进行呢?
显式控制事务
Django提供了一个API来控制数据库事务。
atomic(using = None,savepoint = True)
-
原子性是数据库事务的定义属性。
atomic允许我们创建一个代码块,在该代码块中保证数据库的原子性。如果代码块成功完成,则更改将提交到数据库。如果存在异常,则回滚更改。
首先,我们要导入一个Django的内置模块
from django.db import transaction
接着,就可以使用了
from django.db import transaction with transaction.atomic():
# ORM操作
pass
我们举个例子测试一下
方式一
在"try/except"块中开启事务(且用到with上下文管理器)
1.创建一个项目,新建一个APP(基础操作,这里不再赘述);
2.通过ORM创建生成表:
from django.db import models class UserInfo(models.Model):
username = models.CharField("用户",max_length=32)
balance = models.CharField("余额",max_length=32)
注意啊:踩过的坑,涉及金融计算,涉及小数啊,要求特别精确的,我们用字符串存储。
如果是金融计算的话,我们用一个Decimal来进行计算。
3.我们给数据库加两条数据,用来模拟两个用户之间的转账;
4.配置URL;
5.创建对应的视图函数:
from django.shortcuts import render,HttpResponse
from app01 import models
from django.db import transaction
from django.db.models import F def index(request):
try:
with transaction.atomic():
models.UserInfo.object.filter(id=1).update(balance=F("balance")-100)
models.UserInfo.object.filter(id=2).update(balance=F("balance")+100)
except Exception as e:
return HttpResponse("出现错误<%s>"%str(e))
return HttpResponse("执行成功")
当我们访问index的时候,会进行一次转账操作。
6.现在,我们让他报错:
from django.shortcuts import render,HttpResponse
from app01 import models
from django.db import transaction
from django.db.models import F def index(request):
try:
with transaction.atomic():
models.UserInfo.object.filter(id=1).update(balance=F("balance")-100)
raise '一个错误'
models.UserInfo.object.filter(id=2).update(balance=F("balance")+100)
except Exception as e:
return HttpResponse("出现错误<%s>"%str(e))
return HttpResponse("执行成功")
我们再次查看数据库文件,如果没有数据的原子性操作,我们第一条sql执行完报错,那钱肯定是减去了。
但是,我们进行的是原子性的操作,你会发现钱没有减诶。
完美,没毛病
这是常规的一种操作,另外还有一起其他的方式。
方式二
对整个view视图开启事务
from django.db import transaction @transaction.atomic
def index(request):
# ORM操作
return ....
注意:不要在原子块中进行错误捕获!
当退出原子块的时候,Django会去查看它是否正常退出或者是否有异常来确定是否提交或者回滚。
如果你捕获并处理了原子块中的异常,可能会隐藏Django中发生问题的事实。这样可能会造成非预期的行为。
以上,程序中并没有显示调用commit()提交方法和rollback()回滚方法,原因是Django默认设置为自动提交。当然你可以改变这一切,Django为此提供了相关API:get_autocommit(using=None)和set_autocommit(autocommit, using=None)。
为什么Django使用自动提交
在SQL标准中,每个SQL查询都会启动一个事务,除非一个事务已经处于活动状态。然后必须显式提交或回滚此类事务。
这对应用程序开发人员来说并不总是方便 为了缓解此问题,大多数数据库都提供自动提交模式。启用自动提交并且没有事务处于活动状态时,每个SQL查询都会包含在自己的事务中。换句话说,不仅每个这样的查询都会启动事务,而且事务也会自动提交或回滚,具体取决于查询是否成功。
事务中的保存点
保存点是事务中的标记,使您可以回滚部分事务,而不是完整事务。SQLite(≥3.6.8),PostgreSQL,Oracle和MySQL(使用InnoDB存储引擎时)后端可以使用保存点。其他后端提供了保存点功能,但它们是空操作 - 它们实际上并没有做任何事情。
如果您使用自动提交(Django的默认行为),则保存点不是特别有用。但是,一旦打开事务atomic(),就会构建一系列等待提交或回滚的数据库操作。如果发出回滚,则回滚整个事务。保存点提供了执行细粒度回滚的功能,而不是将执行的完全回滚transaction.rollback()。
当atomic()装饰器嵌套时,它会创建一个保存点以允许部分提交或回滚。强烈建议您使用atomic()而不是下面描述的功能,但它们仍然是公共API的一部分,并且没有计划弃用它们。
这些函数中的每一个都接受一个using参数,该参数应该是行为适用的数据库的名称。如果未using提供参数,则使用"default"数据库。
保存点由以下三个函数控制django.db.transaction:
1)savepoint(using = None)
-
创建一个新的保存点。这标志着已知处于“良好”状态的交易中的一个点。返回保存点ID(sid)。
- 2)savepoint_commit(sid,using = None)
-
提交保存点sid。自创建保存点以来执行的更改将成为事务的一部分。
- 3)savepoint_rollback(sid,using = None)
-
将事务回滚到保存点sid。
如果不支持保存点或数据库处于自动提交模式,则这些功能不执行任何操作。
另外,还有一个实用功能:
- 4)clean_savepoints(using = None)
-
重置用于生成唯一保存点ID的计数器。
以下示例演示了保存点的用法:
from django.db import transaction # open a transaction
@transaction.atomic
def viewfunc(request): a.save()
# transaction now contains a.save() sid = transaction.savepoint() b.save()
# transaction now contains a.save() and b.save() if want_to_keep_b:
transaction.savepoint_commit(sid)
# open transaction still contains a.save() and b.save()
else:
transaction.savepoint_rollback(sid)
# open transaction now contains only a.save()
保存点可用于通过执行部分回滚从数据库错误中恢复。如果你在一个atomic()区块内执行此操作,整个区块仍将被回滚,因为它不知道你已经处理了较低级别的情况!为防止这种情况,您可以使用以下函数控制回滚行为。
get_rollback(using = None)
set_rollback(rollback,using = None)
设置回滚标志以True在退出最内层原子块时强制回滚。这可能有助于在不引发异常的情况下触发回滚。
将其设置为False阻止此类回滚。在此之前,请确保您已将事务回滚到当前原子块中的已知良好保存点!否则,您将破坏原子性并可能发生数据损坏。
至此。转载请注明出处。
[ 本站相关链接:>>Django部署 ]

Django 事务操作的更多相关文章
- Django的ORM实现数据库事务操作
在Django中实现数据库的事务操作 在学习MySQL数据库时,MySQL数据库是支持原子操作的. 什么是数据库的原子操作呢??打个比方,一个消费者在一个商户里刷信用卡消费. 交易正常时,银行在消费者 ...
- Django中-事务操作
如何在Django中进行事务操作呢? 近期,公司里要使用Django开发一套金融相关的系统. 涉及钱了.....安全安全安全 如果钱转到一半,系统崩了,咋办? 如果钱汇到一半,系统崩了,咋办? 如果东 ...
- django基础之day05,orm字段参数,自定义需要的字段,orm中的事务操作
orm字段和参数 charfield varchar integerfield int bigintegerfield bigint emailfield varchar(254) datefield ...
- Django orm进阶查询(聚合、分组、F查询、Q查询)、常见字段、查询优化及事务操作
Django orm进阶查询(聚合.分组.F查询.Q查询).常见字段.查询优化及事务操作 聚合查询 记住用到关键字aggregate然后还有几个常用的聚合函数就好了 from django.db.mo ...
- Django---Django的ORM的一对多操作(外键操作),ORM的多对多操作(关系管理对象),ORM的分组聚合,ORM的F字段查询和Q字段条件查询,Django的事务操作,额外(Django的终端打印SQL语句,脚本调试)
Django---Django的ORM的一对多操作(外键操作),ORM的多对多操作(关系管理对象),ORM的分组聚合,ORM的F字段查询和Q字段条件查询,Django的事务操作,额外(Django的终 ...
- python 全栈开发,Day118(django事务,闭包,客户管理,教学管理,权限应用)
昨日内容回顾 一.django事务 什么是事务 一系列将要发生或正在发生的连续操作. 作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行. 事务处理可以确保除非事务性单元内的所有操 ...
- python---django中orm的使用(5)数据库的基本操作(性能相关:select_related,和prefetch_related重点)(以及事务操作)
################################################################## # PUBLIC METHODS THAT ALTER ATTRI ...
- Django 事务
Django事务 事务是通过将一组相关操作组合为一个,要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠.事务具有4个特性:原子性.一致性.隔离性.持久性. 默认情况下,在Djang ...
- Django框架10 /sweetalert插件、django事务和锁、中间件、django请求生命周期
Django框架10 /sweetalert插件.django事务和锁.中间件.django请求生命周期 目录 Django框架10 /sweetalert插件.django事务和锁.中间件.djan ...
随机推荐
- [Java]LeetCode116. 填充同一层的兄弟节点 | Populating Next Right Pointers in Each Node
Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...
- 本地安装MySQL详细教程
第1章 MySQL的安装与使用 1.1 MySQL安装与配置 1.1.1 MYSQL的安装 1.打开下载的mysql安装文件mysql-5.5.27-win32.zip,双击解压缩,运行“set ...
- 【转】msfvenom使用指南
msfvenom命令行选项如下: Options: -p, --payload <payload> 指定需要使用的payload(攻击荷载).如果需要使用自定义的payload,请使用'- ...
- asp.net core系列 25 EF模型配置(隐藏属性)
一. 隐藏属性概述 隐藏属性也叫影子属性,该属性不是在.net实体类中定义的属性,而是在EFCore模型中为该实体类型定义的属性.这些属性的值和状态完全在变更跟踪器中维护.它有二个功能:(1)当数据库 ...
- C++版 - 剑指Offer 面试题35:第一个只出现一次的字符 解题报告(华为OJ034-找出字符串中第一个只出现一次的字符)
面试题35:第一个只出现一次的字符 题目:在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b.(2006年google的一道笔试题.) 分析: 首先应向确认一下是ASCII字 ...
- SSL / TSL 传输加密算法 初解读
SSL(SecureSocketLayer)是netscape公司提出的主要用于web的安全通信标准,.TLS(TransportLayerSecurity)是IETF的TLS工作组在SSL3.0基础 ...
- IntelliJ IDEA maven项目new里没有package
idea maven项目new里没有package. 如图,idea maven项目new里没有package.: 这是因为java是普通的文件夹,要设置为Source Root 设置好以后可以了.
- python学习第一讲,python简介
目录 python学习第一讲,python简介 一丶python简介 1.解释型语言与编译型语言 2.python的特点 3.python的优缺点 二丶第一个python程序 1.python源程序概 ...
- Connection 对象简介 方法解读 JDBC简介(四)
通过驱动管理器DriverManager的getConnection方法,可以创建到指定URL的连接 Connection conn = DriverManager.getConnection ...
- Mybatis源码之StatementType
在mybatis中StatementType的值决定了由什么对象来执行我们的SQL语句.本文来分析下在mybatis中具体是怎么处理的. StatementType 1.StatementType ...