0

問題を本質まで単純化すると、SQL を埋め込むのではなく、django でこれをネイティブに実行したいと思います。

UPDATE job SET state_id = 100
WHERE job.id = 1 and 0 in (select count(*) from job where state_id = 100);

この SQL ステートメントは、状態 100 のジョブが現在 0 個ある場合にのみ、状態をアトミックに 100 に更新します。

基本的に、状態 100 になるジョブは 1 つだけです。

これはdjangoでネイティブに実行できますか?

4

1 に答える 1

0

私には独自の解決策があると思います...これは、トランザクションがコミットされるまで、基本的にテーブル内のすべての行をロックします。(これはあまり望ましくありません)

# X is the job id to uniquely put into state 100.

with transaction.commit_on_success()
    count = 0
    myjob = None
    for job in Job.objects.select_for_update().all():
        if job.state_id == 100:
            count +=1
        if job.id == X:
            myjob = job
    if count == 0 and myjob:
        myjob.state_id = 100
        myjob.save()

または、どのジョブが固有の状態にあるかを追跡するロック テーブルを作成することもできます。

class StateLock(Model):
    # XXX: could add an expiration column, too.
    state = ForeignKey(State)
    locker = ForeignKey(Job, null=True)  # Use IntegerField until 
                                         # django bug 16715 is fixed!!

そして使う

# lock:
StateLock.objects.filter(state=100, locker=None).update(locker=job.id)

# unlock:
StateLock.objects.filter(state=100, locker=job.id).update(locker=None)

注: django バグ 16715 が修正されるまで、null 許容の外部キーは壊れています。それ以外の場合、生成されたクエリは正しくありません。PositiveIntegerField で置き換えます。

于 2013-03-27T17:15:17.963 に答える