python djangoトランザクションtransactionソース分析の詳細

3855 ワード

python Djangoトランザクション
ネット上でdjango 1について.6の事务资料はとても多くて、しかし1.8のはいかなる资料を探し当てることができなくて、自分で使う时多くの力を费やして駄目で、今使う人を覚えて回り道versionを少なくします:Django 1.8事务の公式のドキュメントの事务の中国语のドキュメントの中で多くの方法を绍介して、いちいち赘述しないで、ドキュメントによってすぐ、以下はatomicの方法のソースコードだけを分析して公式のドキュメントのtransactionに従います.atomicには2つの使い方の装飾器とコンテキストマネージャがあります

# 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')

注:複数のデータベースにルーティングがある場合は、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を正常にロールバックさせるか(この問題に気づかなかったため、何日も試しても成功しなかったので、覚えておいてください)
読書に感謝して、みんなを助けることができることを望んで、みんなの当駅に対する支持に感謝します!