美文网首页
Django 事务详解

Django 事务详解

作者: 大富帅 | 来源:发表于2017-08-04 11:33 被阅读1594次

    Django 1.4 事务默认模式是autocommit模式,每个查询都相当于一个事务,每次查询都直接提交commit事务,
    除非事务被禁止

    Django’s default behavior is to run in autocommit mode. Each query is immediately committed to the database, unless a transaction is active.

    Transaction

    • @transaction.autocommit() 使用django默认事务模式,就是每个查询都相当于一个事务,提交后自动commit
    • @transactioncommit_on_success() ((django 1.8: transaction.atomic() ) 自己控制view或者其他需要事务的代码
    • @transaction.commit_manually() 自己控制commit和rollback,所以代码里面必须显式调用commit 或者 rollback,哪怕只有读的查询

    在view里面的使用:

    1. 装饰器
    @transaction.commit_on_success
    def view():
        a.save()
        b.save()
        return ...
    
    1. with用法
    def func()
        with transaction.commit_on_success():
            a.save()
            b.save()
        return ...
    

    执行查看mysql 的genernal_log

            # django 根据db读写路由,使读和写各生成了一个connect 链接数据库
    
            # 32455 这个是负责查询
            32455 Connect   root@172.16.30.17 on owan
            32455 Query SET NAMES utf8mb4
            32455 Query set autocommit=0
            32455 Query SET SQL_AUTO_IS_NULL = 0
            32455 Query SELECT ... from a WHERE `id` = 20
    
            # 32456 这个是负责更新
            32456 Connect   root@172.16.30.17 on owan
            32456 Query SET NAMES utf8mb4
            32456 Query set autocommit=0
            32456 Query SET SQL_AUTO_IS_NULL = 0
            32456 Query SELECT (1) AS `a` FROM `user_community_signin` WHERE `user_community_signin`.`id` = 20  LIMIT 1
            32456 Query UPDATE a SET `user_id` = ....
    
            # 32455 这个是负责查询 ,第二个查询,依然使用32455这个链接
            32455 Query SELECT ...from b where .`id` = 1
    
            # 32456 依然使用这个32456链接来更新数据
            32456 Query SELECT (1) AS `a` FROM `community_point` WHERE `community_point`.`id` = 1  LIMIT 1
            32456 Query UPDATE b set `id` = ...
    
            # 32456  更新操作commit
            32456 Query commit    
            # (rollback 如果两个更新有任何出错)
            # 32455 Query   rollback    
            # 32456 Query   rollback   
            32455 Quit  
            32456 Quit
    

    如果没有加 transaction.commit_on_success装饰器

            32678 Query UPDATE  a ...
            32678 Query commit
    
            32678 Query UPDATE b ...
            32678 Query commit
    

    让我们理清这个流程:

    • django 默认模式是每个查询都是一个事务,默认模式会在a.save(), b.save()分别提交commit一次,这样就没有两个操作包在一起做事务的功能.所以我们使用了 transaction.commit_on_success 装饰器, 意味着全部操作成功才提交commit,而不是每个查询各自commit
    • 在view里面使用 transaction.commit_on_success, 使这个view的所有操作都是事务执行的
    • 由于django的读写db有设置db路由,使得读写db分别使用了不同的DB链接,看general_log看出来,读和写都有一个connect的操作 读id: 32455, 写id: 32466
    • id: 32466链接负责更新操作,成功之后commit完成事务,如果中途某个更新操作出错,将会回滚事务rollback

    Savepoints

    savepoint是一个可以让事务回滚到指定位置的标记, 默认的事务回滚时整个事务所有操作都回滚,这样开销会大,如果想回滚一部分,那就用savepoint标记某个位置,回滚的时候回到某个点

    from django.db import transaction
    
    @transaction.commit_manually
    def viewfunc(request):
    
      a.save()
      # open transaction now contains a.save()
      sid = transaction.savepoint()
    
      b.save()
      # open 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()
    
      transaction.commit()
    
    

    Mysql 事务

    MySQL默认操作模式就是autocommit自动提交模式。这就表示除非显式地开始一个事务,否则每个查询都被当做一个单独的事务自动执行。我们可以通过设置autocommit的值改变是否是自动提交autocommit模式。
    通过以下命令可以查看当前autocommit模式

    mysql> show variables like 'autocommit';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit | ON |
    +---------------+-------+
    1 row in set (0.04 sec)
    从查询结果中,我们发现Value的值是ON,表示autocommit开启。我们可以通过以下SQL语句改变这个模式
    1
    mysql> set autocommit = 0;
    值0和OFF都是一样的,当然,1也就表示ON。通过以上设置autocommit=0,则用户将一直处于某个事务中,直到执行一条commit提交或rollback语句才会结束当前事务重新开始一个新的事务。

    相关文章

      网友评论

          本文标题:Django 事务详解

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