视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
关于pythondjango事务transaction源码分析介绍
2020-11-27 14:25:23 责编:小采
文档


这篇文章主要介绍了python django事务transaction源码分析详解的相关资料,需要的朋友可以参考下

python Django事务

网上关于django1.6的事务资料很多,但是1.8的却搜不到任何资料,自己要用的时候费了不少劲就是不行,现在记下要用的人少走弯路 version:Django 1.8 事务官方文档 事务中文文档 里面介绍很多方法,不一一赘述,按照文档即可,下面只分析下atomic方法的源码 按照官方文档 transaction.atomic 有两种用法装饰器和上下文管理器

# atomic() 方法 
# from django.db import transaction
###################
# atomic()
###################
def atomic(using=None, savepoint=True): # 装饰器和上下文管理器必须.()调用方法,因为真正的处理是该方法返回的实例,不是该方法本身
 if callable(using):
 return Atomic(DEFAULT_DB_ALIAS, savepoint)(using)
 # Decorator: @atomic(...) or context manager: with atomic(...): ...
 else:
 return Atomic(using, savepoint)
##########################################
# Atomic类 省略了非核心内容
############################################
class Atomic(ContextDecorator):
 def init(self, using, savepoint):
 self.using = using
 self.savepoint = savepoint
 def enter(self):
 connection = get_connection(self.using)
 sid = connection.savepoint() # 进入with创建一个保存点
 # .............do
 def exit(self, exc_type, exc_value, traceback):
 if connection.in_atomic_block:
 # do.............
 if sid is not None:
 try:
 connection.savepoint_commit(sid) # 提交事务
 except DatabaseError:
 try:
 connection.savepoint_rollback(sid) # 捕获数据库异常回滚
 connection.savepoint_commit(sid)
 except Error:
 connection.needs_rollback = True
 raise
 ## 还有一段代码是exec_type收到其他程序异常时候 全局回滚,此处省略
 # do.................
###############################
# ContextDecorator
#################################
class ContextDecorator(object):
 def call(self, func):
 def inner(*args, **kwargs):
 with self: # 把函数放进self的with上下文管理器,效果with相同,只是控制细粒度不同
 return func(*args, **kwargs)
 return inner

python MySQLdb

class Tran():
 def init(self, conn=None, close=True):
 if conn is None: # 创建数据库链接
 print 'init'
 self.conn = conn_tbkt()
 self.cur = self.conn.cursor()
 self.sql = []
 def enter(self): # 上下文管理器返回 sql语句列表 with Tran('tbkt_pxb') as sqls:
 print 'enter'
 return self.sql # sql.append('select 1')
 def exit(self, exc_type, exc_val, exc_tb):
 print 'exit'
 try:
 print self.sql # 执行sql
 for s in self.sql:
 self.cur.execute(s)
 self.conn.commit()
 except: # 可以捕获所有异常(django事务如果中间出现程序异常终止无法回滚)
 try: # 回滚本身也是sql执行,也有可能失败
 import traceback
 traceback.print_exc()
 print 'rollback'
 self.conn.rollback()
 except:
 print u'回滚失败'
 finally:
 self.cur.close()
 self.conn.close()

更细粒度的回滚:

# 在事务块中@atomic() 或者 with atomic():
sid = transaction.savepoint('tbkt_pxb')
try:
 # do ..........
except:
 transaction.savepoint_rollback(sid, 'tbkt_pxb')

注意:如果有多个数据库有路由,则需要指定和路由返回一致的useing: math2下的model需要事务,即使ziyuan_new和default是同一个库,也必须使用useing=ziyuan_new

 ziyuan_app = ['math2', 'ziyuan']
 if model._meta.app_label in ziyuan_app:
 return "ziyuan_new"
 return 'default'

调用时候必须.()方法调用

atomic块中必须注意try的使用,如果手动捕获了程序错误会导致atomic包装器捕获不到异常,也就不会回滚。要么try内代码不影响事务操作,要么就捕获异常后raise出,让atomic可以正常回滚(就是因为没有注意到这个问题,导致尝试了好几天都没成功,切记)

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

下载本文
显示全文
专题