5 votes

Obtenir l'élément de travail suivant dans Django avec PostgreSQL

Imaginez que vous avez une table simple avec des éléments de travail :

|ID |PROPRIÉTAIRE|...
+---+-----+---
|123|     |...
|456|     |...
|789|     |...

Nous voulons fournir une API http pour obtenir le prochain élément de travail qui n'a pas encore de propriétaire.

Nous utilisons PostgreSQL.

Nous accédons à la table avec Django-ORM.

Je suppose qu'il y a plusieurs conditions de concurrence si l'API est accédée simultanément par de nombreux utilisateurs.

Comment puis-je m'assurer avec les outils donnés (PostgreSQL, Django) que toutes les conditions de concurrence sont résolues (c'est une erreur majeure si un élément de travail est attribué à deux utilisateurs ou plus).

2voto

munsu Points 796

Avec Django 1.11, select_for_update a commencé à prendre en charge skip_locked. Cela signifie que vous pouvez économiser sur les appels à save() car vous n'êtes pas obligé de l'assigner à un propriétaire tout de suite.

Par exemple, en s'appuyant sur la réponse de @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'])

# traiter work_item

vous pouvez faire:

with transaction.atomic():
    work_item = WorkItem.objects.select_for_update(skip_locked=True).filter(owner__isnull=True).first()
    work_item.owner = request.user
    # traiter work_item, éditer d'autres champs
    work_item.save()

Avec skip_locked=True, la transaction saute la ligne verrouillée, et est donc non bloquante. En prime, vous n'aurez besoin de sauvegarder dans la base de données qu'une seule fois.

1voto

user73657 Points 271

Avec select_for_update:

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/fr/1.11/ref/models/querysets/#select-for-update

select_for_update s'assurera qu'une seule connexion peut mettre à jour les lignes correspondantes jusqu'à ce que la transaction soit terminée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X