在Django中进行数据库事务管理

数据库事务

基本概念

事务是指作为单个逻辑工作单元执行的一系列操作,这些操作具有原子性,即这些操作要么完全地执行,要么完全地不执行。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。

事务属性

事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性

  • 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
  • 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
  • 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  • 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

事务举例

  1. 银行转账

假定A账户目前有100元,B账户和C账户同时向A账户转账100元。这个时候,我们需要保证:

  • B账户减少100元后,A账户增加100元。假使交易途中发生故障,B账户不应减少100元,A账户也不应增加100元。(原子性、一致性)
  • C账户减少100元后,A账户增加100元。假使交易途中发生故障,C账户不应减少100元,A账户也不应增加100元。(原子性、一致性)
  • B账户交易、C账户交易过程中,应有先后次序,交易不可在同一个余额上重复执行,以确保交易后A账户余额正确。(隔离性)
  • 交易记录应在交易完成后永久记录。(持久性)

可见,转账事务具有上述四个属性,因此在处理转账时,需要将其对待为事务。

  1. 公众号抢票操作

假定A活动目前有100张余票,B同学和C同学同时需要抢票一张。这个时候,我们需要保证:

  • A活动减少1张票后,B同学手中应多一张活动票。假使抢票途中发生故障,B不应获得1张活动票,A活动也不应减少1张票。(原子性、一致性)
  • A活动减少1张票后,C同学手中应多一张活动票。假使抢票途中发生故障,C不应获得1张活动票,A活动也不应减少1张票。(原子性、一致性)
  • B同学抢票、C同学抢票过程中,应有先后次序,交易不可在同一个余票基础上重复执行,以确保交易后A活动余票正确。(隔离性)
  • 抢票记录应在抢票完成后永久记录。(持久性)

可见,抢票事务具有上述四个属性,因此在处理抢票时,需要将其对待为事务。

MySQL中的事务管理

事务控制语句

  • BEGINSTART TRANSACTION;显式地开启一个事务;
  • COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的;
  • ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
  • SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;
  • RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
  • ROLLBACK TO identifier;把事务回滚到标记点;
  • SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。

MySQL事务处理主要使用的方法

  1. 用 BEGIN, ROLLBACK, COMMIT来实现
  • BEGIN 开始一个事务
  • ROLLBACK 事务回滚
  • COMMIT 事务确认
  1. 直接用 SET 来改变 MySQL 的自动提交模式:
  • SET AUTOCOMMIT=0 禁止自动提交
  • SET AUTOCOMMIT=1 开启自动提交

在 Django 中进行事务管理

在上面的例子中我们看到,若是直接在项目中使用MySQL数据库并使用原始的SQL语句进行事务管理,会是一件相当麻烦的事情。但是不必担心,如果后端使用的是Django框架的话,Django框架就已经提供了好几种方式来控制和管理数据库事务,并且与使用数据库无关。

Django框架默认的事务行为

SQL的标准中指出,除非已经存在一个开启的事务,否则每个SQL查询都会开启一个新事务。这些事务后续必须被明确的提交或者回滚。

这对应用开发者来说并不是很方便。为了降低这种不便性,大部分数据库提供了自动提交模式。Django亦直接提供了自动提交模式,并默认打开了自动提交。它表现形式为:每次数据库操作会立即被提交到数据库中,除非这个事务仍然处于激活状态。

显式地控制事务

Django 提供了单独 API 来控制事务。

atomic(using=None, savepoint=True)

原子性是数据库事务的一个属性。使用上述 **atomic **,我们就可以创建一个具备原子性的代码块。一旦代码块正常运行完毕,所有的修改会被提交到数据库。反之,如果有异常,更改会被回滚。

atomic管理起来的代码块还可以内嵌到方法中。这样的话,即便内部代码块正常运行,如果外部代码块抛出异常的话,它也没有办法把它的修改提交到数据库中。

atomic 的使用方法如下:

  1. 当做装饰器来使用
from django.db import transaction

@transaction.atomic
def viewfunc(request):
    ## This code executes inside a transaction.
    do_stuff()
  1. 当作上下文管理器来使用
 
 

你可能感兴趣的:(Django,事务,transaction,数据库,并发)