美文网首页
Django transaction (事物)

Django transaction (事物)

作者: 徐德东 | 来源:发表于2018-01-15 12:23 被阅读0次

注:1.6或者1.8以后的版本,请直接跳至标题4

一:背景

在处理http请求中,经常会遇到复杂的对数据库操作的业务逻辑。比如创建修改一系列的相关的对象。但是一旦其中某一处执行失败或出现异常,都要求回退到执行前的状态。这时候数据库的事务管理就非常重要了。

二:TransactionMiddleWare

可以通过settings.py中启用中间件来打开全局的事物管理。这个不推荐,一般不需开启,并且这个中间在1.8版本中删除。

所以settings.py文件中下面这个元组中可以将TransactionMiddleware代码行注释掉。到views.py视图函数里去添加事物处理。哪里需要就在那里添加,控制比较灵活。

MIDDLEWARE_CLASSES = (

    'django.middleware.cache.UpdateCacheMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',

    'django.middleware.common.CommonMiddleware',

    #'django.middleware.transaction.TransactionMiddleware',  # 事务管理中间件

    'django.middleware.cache.FetchFromCacheMiddleware',

)

在中间件执行顺序中,位于TransactionMiddleware之后的中间件都将被纳入事务管理。

三:transaction.commit_on_success

在django1.6之前,transaction模块提供了以下几种方法供事务管理,注意以下方法将在1.8版本全部删除。

可用作装饰器的autocommit、commit_on_success、commit_manually

行代码级别的commit、rollback、savepoint、savepoint_rollback、savepoint_commit等

这里只讲一下最常用的commit_on_success

from django import transaction

1、装饰器用法

@transaction.commit_on_success()

def index(request):

    pass

整个index的内容都会被纳入事务管理,出现异常则回滚,否则等待整个index方法执行成功后再提交至数据库。

2、代码块用法,推荐

def index(request):

    work1()

    try:

        with transaction.commit_on_success():

            work2()

    except Exception:

        pass

    work3()


这里会将work2纳入事务管理,work1和work3没有纳入。在例子中with外层使用了try抓取异常,这能保证事务管理的同时又能使view正常执行,返回正常的response[200]而不是直接抛出异常500。


需要注意的是,假如你在work2中使用了try抓取异常,那么抓取的这部分将不会进行事务管理。示例代码如下

def index(request):

    work1()

    try:

        with transaction.commit_on_success():

            a.save()  # in transaction

            try:

                b.save()  # NOT in transaction

            except:

                pass

            c.save()  # in transaction

    except:

        pass

四:transaction.atomic

从django1.6开始,django提供了atomic来代替之前几种方法。

依据Django1.6的文档,“Django提供了一种简单的API去控制数据库的事务交易...原子操作用来定义数据库事务的属性。原子操作允许我们在数据库保证的前提下,创建一堆代码。如果这些代码被成功的执行,所对应的改变也会提交到数据库中。如果有异常发生,那么操作就会回滚。”

用法和上例一致,可以采用装饰器用法或代码块用法,推荐代码块。

def index(request):

    try:

        with transaction.atomic():

            work2()

    except Exception:

        pass

五:多数据库的事务管理坑

注意!注意!注意!当给django配置了多个数据库时,所有事务管理的方式都只会影响settings.py DATABASES中默认的数据库(default)。如:

DATABASES = {

        'default': {

            'ENGINE': 'django.db.backends.mysql',

            ......

        },

        'zoo': {

            'ENGINE': 'django.db.backends.mysql',

            ......

        }

}

此时如果版本控制中有对zoo数据库的操作,django默认会跑去default数据库中进行回滚,结果当然是静默失败。

对此,只能显式声明要操作的数据库,哪怕django完全可以通过代码追溯到操作的数据库是哪个,目前的django 1.9版本仍然如此。

def index(request):

    try:

        with transaction.atomic(using='zoo'):  # transaction.commit_on_success(using='zoo')

            work2()

    except Exception:

        pass

希望以后的版本会改进此处。

六:关于性能

拿MySQL/InnoDB举例

MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关。

MyISAM:不支持事务,用于只读程序提高性能

InnoDB:支持ACID事务、行级锁、并发

Berkeley DB:支持事务

事务的ACID属性只能通过限制数据库的同步更改来实现,从而通过对修改数据加锁来实现。直到事务触发COMMIT或ROLLBACK语句时锁才释放。 缺点是后面的事务必须等前面的事务完成才能开始执行,吞吐量随着等待锁释放的时间增长而递减。

MySQL/InnoDB通过行级锁来最小化锁竞争。这样修改同一table里其他行的数据没有限制,而且读数据可以始终没有等待。

MySQL/InnoDB默认给每条SQL语句都声明为一个事务,即使大部分数据库操作中都用不到事务管理。

事务设计原则

1,保持事务短小 

2,尽量避免事务中rollback 

3,尽量避免savepoint 

4,默认情况下,依赖于悲观锁 

5,为吞吐量要求苛刻的事务考虑乐观锁 

6,显示声明打开事务 

7,锁的行越少越好,锁的时间越短越好

django同样遵循此原则,从1.8亦或1.9开始,django默认将每条SQL语句都取消事务声明,用来减少每次http请求所造成的数据库操作未使用的事务管理消耗,提升性能,只有手动使用transaction.atomic才会保留MySQL的事务管理。

相关文章

  • Django transaction (事物)

    注:1.6或者1.8以后的版本,请直接跳至标题4 一:背景 在处理http请求中,经常会遇到复杂的对数据库操作的业...

  • 事务

    2.事务的语句开始事物:BEGIN TRANSACTION提交事物:COMMIT TRANSACTION回滚事务:...

  • spring cloud 事物测试

    熔断事物测试 前提:现有事物测试范例 transaction -demo-1(A),transaction -de...

  • Transaction事物、hibernate事物管理

    后面用到spring框架的时候,都不需要在这里添加事物,都会交给Spring去管理。 如果不想手动提交事物,可以在...

  • Django 事务管理

    Django Transaction: 目的:保证操作的原子性,操作必须全部成功,否则就会回滚操作。 用法: 装饰...

  • 事物补偿模式 Compensating Transaction

    为了保证最终一致性, 在错误发生时, 沿着整个错误的传递路径进行undo操作. 对于复杂的工作流来说, 尽可能保证...

  • JDBC编程:JDBC高级编程

    事物处理 批量更新 返回自动主键 DAO 1,事物处理 什么是事物? 事务(Transaction):数据库中保证...

  • django.db.transaction.Transactio

    前一段时间在sentry上看到了这样一个错误“django.db.transaction.TransactionM...

  • django 事务嵌套 transaction nesting

    django 官方文档stack overflow 关于django事务嵌套问题

  • 31、django的事务_transaction

    背景 在写项目时,特别是view中,我们可能需要进行多个业务操作(不仅仅是操作sql)。比如说:在编辑case的接...

网友评论

      本文标题:Django transaction (事物)

      本文链接:https://www.haomeiwen.com/subject/jhvroxtx.html