2017-08-25 6 views
1

コードがtransaction.atomicブロック内で実行されているときに例外が発生すると、データベースハンドラはロールバックが必要とマークされます。 、まだそのtransaction.atomicブロック内で、後続のクエリが実行されている場合は、次のエラーが発生します。この時点でTransactionManagementErrorルート例外を覆い隠す

TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic'

を、実際のルート・エラーは、あなたがジャンプする必要が残して、アクセスに隠さとはかなり困難ですDjangoのトランザクションコードに変換します。このエラーが発生する可能性があり

簡単な例:

def someview(request): 
    with transaction.atomic(): 
     // do some things 
     instance = SomeModel.objects.create(...) 
     // some other db queries 

@receiver(post_save, sender=SomeModel) 
def non_critical_side_effect(
    sender, instance, created, raw, using, update_fields, **kwargs 
): 
    try: 
     // some query that causes a database error 
     SomeModelLog.objects.create(some_non_none_field=None) 
    except IntegrityError: 
     //notify ourselves, go on 
     pass 

どのようにあなたが本当にあなたがこのシナリオを打ったときに何が起こっているか仕事か、そしてどのようにあなたが定期的にこのシナリオを回避するのですか?

(以下自己の答え - しかし、相手の思考で純粋に興味を持って!)

答えて

1

あなたはdjango.db.transaction.atomicコンテキストマネージャを使用しているとTransactionManagementErrorで困惑している場合、あなたはexc_valueときの値を調べることによって、根本原因を特定することができますneeds_rollbackTrueに設定し、django.db.transaction.Atomic.__exit__に設定します。これは、トランザクションをロールバックする必要性を促す例外でなければなりません。あなたは、より大きなtransaction.atomicブロックを必要としない場合transaction.atomic

  • のコードの大きなブロックを包む

    • 避けるには、どんなことを確認してください:最初の場所でこのエラーを回避する観点から

      は、私は2つのアプローチを採用していますロールバックされるトランザクション全体を必要とせずに失敗する可能性があるこのブロックの部分は、それぞれのサブトランザクションでラップされます。

      def someview(request): 
          with transaction.atomic(): 
           // do some things 
           SomeModel.objects.create(invalid_field=123) 
      
      @receiver(post_save, sender=SomeModel) 
      def non_critical_side_effect(
          sender, instance, created, raw, using, update_fields, **kwargs 
      ): 
          try: 
           with transaction.atomic(): 
            // some query that causes a database error 
          except IntegrityError: 
           // notify ourselves, go on 
           pass 
      

    私の元の例では、ビューは、次に出現するデータベースエラーが発生したシグナルハンドラにもかかわらず、実行を継続することができるように修正しました

  • 関連する問題