2

トランザクションとセロリのタスクについて質問があります。したがって、同じテーブル/レコードにアクセスするトランザクションとセロリ タスクがある場合、競合状態が発生することは当然のことです。

ただし、次のコードを検討してください。

def f(self):
   # function of module that inherits from models.Model
   self.field_a = datetime.now()

   self.save()
   transaction.commit_unless_managed()

   # depending on the configuration of this module
   # this might return None or a datetime object.
   eta = self.get_task_eta()

   if eta:
       celery_task_do_something.apply_async(args=(self.pk, self.__class__),
                                            eta=eta)
   else:
       celery_task_do_something.delay(self.pk, self.__class__)

セロリのタスクは次のとおりです。

def celery_task_do_something(pk, cls):

    o = cls.objects.get(pk=pk)

    if o.field_a:
        # perform something
        return True
    return False

ご覧のとおりtransaction.commit_unless_managed、django トランザクションは現在管理されていないため、タスクを作成する前に呼び出してコミットする必要があります。

ただし、セロリ タスクを実行すると、フィールドfield_aは設定されません。

私の質問:

タスクを作成する前にコミットするので、競合状態が発生する可能性はありますか?

追加情報

  • Postgres バージョン 9.1 を使用しています

  • すべてのトランザクションは READ COMMITTED 分離レベルで実行されます

  • エンジンを備えた別のデータベースでdowant.lib.db.backends.postgresql_psycopg2_debugger field_aは既に設定されており、タスクは期待どおりに機能します。エンジンを使用dowant.lib.db.backends.postgresql_psycopg2_hstore_readyすると、説明されている問題が発生します (エンジンに関連しているかどうかは不明です)。

  • セロリのバージョンは2.2

  • さまざまなデータベースを試しました。エンジンが変更された場合を除いて、同じ動作です。だから私はこれに言及したのです。

どうもありがとう。

4

2 に答える 2

1

self.__class__.objects.select_for_update().get(pk=self.pk)前に追加しsaveて、何が起こるか見てみてください。

コミットが完了するまで、この行へのすべての読み取りをブロックする必要があります。

于 2012-10-28T16:36:02.040 に答える