Rennbedingungen im Django
Hier ist ein einfaches Beispiel einer django-Ansicht mit einer möglichen race-condition:
# myapp/views.py
from django.contrib.auth.models import User
from my_libs import calculate_points
def add_points(request):
user = request.user
user.points += calculate_points(user)
user.save()
Race-Bedingung sollte klar sein: Ein Benutzer kann diese Anfrage zweimal, und könnte die Anwendung möglicherweise die Ausführung von user = request.user
gleichzeitig, wodurch eine Anforderung zum überschreiben der anderen.
Nehme an, dass die Funktion calculate_points
ist relativ kompliziert, und macht Berechnungen, basierend auf alle Arten von seltsamen Sachen, die nicht platziert werden kann in einer einzigen update
und würde schwierig sein, um in einer gespeicherten Prozedur.
So, hier ist meine Frage: Welche Art von locking-Mechanismen verfügbar sind, um django, um mit Situationen wie dieser?
InformationsquelleAutor der Frage Fragsworth | 2009-06-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Django 1.4+ unterstützt select_for_updatein früheren Versionen, die Sie ausführen können raw-SQL-Abfragen z.B.
select ... for update
die je nach der zugrunde liegenden DB-Schloss, die Reihe von Aktualisierungen, können Sie tun, was Sie will, die Zeile bis zum Ende der Transaktion. z.B.InformationsquelleAutor der Antwort Anurag Uniyal
Als von Django 1.1 Sie können die ORM ist F () - Ausdrücke, um zu lösen dieses problem.
Weitere details finden Sie in der Dokumentation:
https://docs.djangoproject.com/en/1.8/ref/models/instances/#updating-attributes-based-on-existing-fields
https://docs.djangoproject.com/en/1.8/ref/models/expressions/#django.db.models.F
InformationsquelleAutor der Antwort bjunix
Sperren der Datenbank ist der Weg hier zu gehen. Es gibt Pläne für das hinzufügen einer "select for update" - Unterstützung für Django (hier), aber jetzt das einfachste wäre die Verwendung von raw-SQL-UPDATE der user-Objekt aus, bevor Sie beginnen, das Ergebnis zu berechnen.
Pessimistischen locking wird unterstützt von Django 1.4 s ORM, wenn der zugrunde liegende DB (wie z.B. Postgres) unterstützt. Finden Sie die Django 1.4a1 release notes.
InformationsquelleAutor der Antwort zooglash
Haben Sie viele Möglichkeiten, um single-thread-diese Art der Sache.
Einem standard-Ansatz ist Update Erste. Sie machen ein update, die nutzen eine exklusive Sperre auf die Zeile; dann tun Sie Ihre Arbeit; und schließlich einen commit der änderung. Damit dies funktioniert, müssen Sie die bypass-ORM-caching.
Anderen standard-Ansatz ist, um eine separate, single-threaded-Anwendung-server, der isoliert die Web-Transaktionen, die von der komplexen Berechnung.
Ihre web-Anwendung kann eine Warteschlange erstellen der scoring-Anfragen, erzeugen Sie einen separaten Prozess, und schreiben Sie dann die scoring-Anfragen an diese Warteschlange. Das laichen kann in Django ' s
urls.py
so geschieht es auf der web-app-startup. Oder es können in getrenntenmanage.py
admin-Skript. Oder es kann getan werden "nach Bedarf", wenn die erste scoring-Anfrage versucht wird.Können Sie auch erstellen Sie eine separate WSGI-Geschmack der Webserver mit Werkzeug akzeptiert WS Anfragen via urllib2. Wenn Sie eine single-port-Nummer für diesen server, die Anfragen sind in der Warteschlange für TCP/IP. Wenn Ihr WSGI-handler hat einen thread, dann haben Sie erreicht serialisiert single-threading. Das ist etwas mehr skalierbar, da die scoring-engine ist ein WS-Anfrage und kann überall laufen.
Noch ein anderer Ansatz ist, irgendeine andere Ressource, die werden erworben und gehalten, die für die Berechnung.
Ein Singleton-Objekt in der Datenbank. Eine einzelne Zeile in eine einzigartige Tabelle, die aktualisiert werden können mit einer session-ID zu beschlagnahmen Kontrolle; update mit session-ID
None
Kontrolle abzugeben. Die wesentlichen update umfasst einenWHERE SESSION_ID IS NONE
filter, um sicherzustellen, dass das update fehlschlägt, wenn die Sperre gehalten wird, die von jemand anderem. Das ist interessant, denn es ist von Natur aus race-free-es ist ein einzelnes update -- keine SELECT-UPDATE-Sequenz.Einem Garten-Vielfalt semaphore können genutzt werden, außerhalb der Datenbank. - Warteschlangen (im Allgemeinen) sind einfacher zu arbeiten, als mit einer low-level-semaphore.
InformationsquelleAutor der Antwort S.Lott
Kann dies zu kurz gedacht deine situation, aber was ist nur ein JavaScript-link Ersatz? In anderen Worten, wenn der Benutzer auf den link klickt oder die Schaltfläche wickeln Sie die Anfrage in eine JavaScript-Funktion, die sofort deaktiviert /"greys" den link und ersetzt den text mit "Lade..." oder "Anfrage Absenden..." info " oder etwas ähnliches. Würde, dass die Arbeit für Sie?
InformationsquelleAutor der Antwort Wayne Koorts
Nun, Sie benutzen müssen:
InformationsquelleAutor der Antwort dingyaguang117