Django 1.6は、1.5からのトランザクション管理のリホールの一部として@transaction.atomic
を提案しています。
私はDjango管理コマンドによって呼び出される関数を持っています。このコマンドはcronによって呼び出されます。つまり、この場合、トランザクションをトリガーするHTTP要求はありません。スニペット:
from Django.db import transaction
@transaction.commit_on_success
def my_function():
# code here
上記のコードブロックでは、 commit_on_success
はmy_function
で行われたすべての作業に単一のトランザクションを使用します。
@transaction.commit_on_success
を@transaction.atomic
に置き換えると、同じ動作になりますか? @transaction.atomic
ドキュメントの状態 :
アトミック性は、データベーストランザクションの定義プロパティです。 atomicを使用すると、データベースの原子性が保証されるコードブロックを作成できます。コードブロックが正常に完了すると、変更がデータベースにコミットされます。例外がある場合、変更はロールバックされます。
それらが同じ振る舞いをもたらすと思います。正しい?
はい。以前にcommit_on_success
を使用した場所でatomic
を使用する必要があります。
ただし、新しいトランザクションシステムはより堅牢で一貫性があるように設計されているため、異なる動作が見られる可能性があります。たとえば、データベースエラーをキャッチして続行しようとすると、TransactionManagementError
が表示されますが、以前の動作は未定義で、おそらくケースに依存していました。
ただし、適切に作業を行っている場合は、すべてが同じように機能し続ける必要があります。
このテーマについて読んだドキュメントに基づいて、これらのデコレータがネストされている場合には大きな違いがあります。
2つのatomic
ブロックのネストは、2つのcommit_on_success
ブロックのネストと同じようには機能しません。
問題は、これらのブロックから得たい2つの保証があることです。
ブロックがネストされている場合、両方の保証を提供することは不可能です。最も内側のブロックを出た後、最も外側のブロックを出る前に例外が発生した場合、次の2つの方法のいずれかで失敗する必要があります。
ここに違いがあります。 commit_on_success
を使用すると、最も内側のブロックに耐久性が与えられますが、最も外側のブロックには原子性がありません。 atomic
を使用すると、最も外側のブロックに原子性が与えられますが、最も内側のブロックには耐久性がありません。
ネストの場合に単純に例外を発生させると、問題が発生するのを防ぐことができます。一番内側のブロックは常に例外を発生させるため、永続性は保証されません。しかし、これはある程度の柔軟性を失います。
より良い解決策は、あなたが求めているものについてより細かくすることです。原子性と耐久性を個別に要求できる場合は、ネストを実行できます。耐久性を要求するすべてのブロックが、原子性を要求するブロックの外側にあることを確認する必要があります。ブロック内で原子性を要求する永続性を要求するには、例外を発生させる必要があります。
atomic
は原子性部分を提供することになっています。 Django 1.6.1には耐久性を要求できるデコレータがありません。コードレビューで posted を書きました。