2017-04-28 4 views
5
とジャンゴに次の作業項目を取得します

あなたは仕事のアイテムを持つ単純なテーブルを持っている想像:PostgreSQLの

|ID |OWNER|... 
+---+-----+--- 
|123|  |... 
|456|  |... 
|789|  |... 

私たちは、所有者を持っていない次の作業項目を取得するためのHTTP APIを提供したいですまだ。

私たちはPostgreSQLを使用します。

Django-ORMを使用してテーブルにアクセスします。

多くのユーザーが同時にAPIにアクセスできる場合は、いくつかの競合条件があると思います。

すべての競合条件が解決された(PostgreSQL、Django)与えられたツール(PostgreSQL、Django)を使用するにはどうすればよいでしょうか(2人以上のユーザーに作業項目が与えられた場合、 select_for_update

答えて

2

Django 1.11では、select_for_updateskip_lockedをサポートし始めました。つまり、すぐに所有者に割り当てる必要がないので、save()のコールを節約することができます。例えば

は、@ user73657の答えの上に構築:

with transaction.atomic(): 
    work_item = WorkItem.objects.select_for_update().filter(owner__isnull=True).first() 
    work_item.owner = request.user 
    work_item.save(update_fields=['owner']) 

# process work_item 

あなたが行うことができます:skip_locked=True

with transaction.atomic(): 
    work_item = WorkItem.objects.select_for_update(skip_locked=True).filter(owner__isnull=True).first() 
    work_item.owner = request.user 
    # process work_item, edit other fields 
    work_item.save() 

を、トランザクションがロックされた行をスキップし、したがって、非ブロッキングです。ボーナスとして、db に一度だけに保存する必要があります。

+1

うわー、「SKIP LOCKED」がよく見えます。私はこの記事を見つけました:詳細を説明しているhttps://blog.2ndquadrant.com/what-is-select-skip-locked-for-in-postgresql-9-5/ – guettli

1

with transaction.atomic(): 
    work_item = WorkItem.objects.select_for_update().filter(owner__isnull=True).first() 
    work_item.owner = request.user 
    work_item.save(update_fields=['owner']) 

# process work_item 

https://docs.djangoproject.com/en/1.11/ref/models/querysets/#select-for-update

select_for_updateは、トランザクションが終了するまで唯一つの接続が一致する行を更新できることを確認します。