1

私が書いた一連のセロリタスクがあります。これらの各タスクは、ほんの一例として、著者 ID をパラメーターとして取り、その著者の書籍ごとに最新の価格を取得してデータベースに保存します。

@transaction.commit_on_successDjango のデコレータをタスクに追加して、タスクにトランザクションを追加したいと考えています。いずれかのタスクがクラッシュした場合、タスク全体が失敗し、データベースには何も保存されないようにしたいと考えています。

著者の書籍の価格をチェックする 12 人ほどのセロリ ワーカーがいますが、この単純なトランザクション ロジックが私の Postgres データベースでロックや競合状態を引き起こすのではないかと考えています。

私は掘り下げて、django-celery-transactionsと呼ばれるこのプロジェクトを見つけましたが、この背後にある実際の問題と、このプロジェクトが解決しようとしたことをまだ理解していません。

4

2 に答える 2

1

その理由は、Djangoビューでは、デコレータを適用した場合、ビューが終了するまでDBトランザクションがコミットされないためです。ビューが戻ってコミットをトリガーする前に、ビュー内で、DBトランザクションがすでにコミットされていること、つまりそれらのエントリがDBコンテキストに存在することを期待するタスクを呼び出すことができます。

この競合状態(ビューの前にタスクが開始され、結果としてトランザクションが終了する)を防ぐために、手動で管理するか、前述のモジュールを使用して自動的に処理することができます。

たとえば、あなたの場合に失敗する可能性のある例は、新しい著者を追加していて、そのすべて/すべての本の価格を取得するタスクがある場合です。新しい作成者トランザクションのコミットが完了する前にタスクが実行された場合、タスクはまだ存在しないIDで作成者をフェッチしようとします。

于 2012-10-19T07:28:37.700 に答える
1

これは、データベースのトランザクション分離レベル、価格の更新を確認する頻度、価格が変更されると予想される頻度など、いくつかの要因によって異なります。たとえば、標準の PostgreSQL をストックするために 1 秒あたり非常に多くの更新を行っていた場合、トランザクションで同じ select ステートメントを複数回実行すると、異なる結果が得られる可能性があります。

データベースは同時実行性を処理するように最適化されているため、これが問題になることはないと思います。特に、価格を取得するまでトランザクションを開かない場合 (つまり、タスクをデコレートするのではなく、コンテキスト マネージャーを使用する場合)。なんらかの理由で将来的に処理が遅くなった場合は、最適化します (価格を取得する頻度を減らす、データベース構成を微調整するなど)。

他の質問については、django-celery-transactions は、Django と Celery の間の競合状態を防ぐことを目的としています。1 つの例は、新しく作成されたオブジェクトの主キーをタスクに渡す場合です。タスクは、ビューのトランザクションがコミットされる前にオブジェクトを取得しようとする場合があります。ブーム!

于 2012-10-19T11:51:16.380 に答える