Atominkrement eines Zählers im Django
Ich versuche, atomar Inkrement ist ein einfacher counter in Django. Mein code sieht wie folgt aus:
from models import Counter
from django.db import transaction
@transaction.commit_on_success
def increment_counter(name):
counter = Counter.objects.get_or_create(name = name)[0]
counter.count += 1
counter.save()
Wenn ich verstehe, Django korrekt, diese sollten wickeln Sie die Funktion in eine Transaktion und machen die Schrittweite atomic. Aber es funktioniert nicht und es ist eine race-condition in der counter-update. Wie kann dieser code aus thread-sicher?
InformationsquelleAutor der Frage Björn Lindqvist | 2009-10-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Neu in Django 1.1
oder mit ein F-Ausdruck:
Thema des race-Bedingung, die mit diesem Ansatz verbundenen wurde Hinzugefügt, um die offizielle Dokumentation.
InformationsquelleAutor der Antwort Oduvan
In Django 1.4 es ist Unterstützung für SELECT ... FOR UPDATE Klauseln, die mithilfe von Datenbank-sperren, um sicherzustellen, dass keine Daten zugreift, die gleichzeitig durch Fehler.
InformationsquelleAutor der Antwort Emil Stenström
Halten Sie es einfach und aufbauend auf @Oduvan Antwort:
Der Vorteil hier ist, dass, wenn das Objekt erstellt wurde, in der ersten Anweisung, Sie nicht zu tun haben, keine weiteren updates.
InformationsquelleAutor der Antwort mlissner
Wenn Sie brauchen nicht zu wissen, den Wert des Zählers, wenn Sie es, die top-Antwort ist definitiv Ihre beste Wette:
Diese erzählt Ihrer Datenbank hinzufügen 1 um den Wert des
count
was es tun kann, sehr gut, ohne zu blockieren andere Operationen. Der Nachteil ist, dass Sie haben keine Möglichkeit zu wissen, wascount
Sie stellen nur. Wenn zwei threads gleichzeitig drücken Sie auf diese Funktion, Sie würden beide sehen den gleichen Wert, und beide sagen, die db hinzufügen 1. Die db würde am Ende hinzufügen 2 wie erwartet, aber man weiß nicht, welche eins zuerst ging.Wenn Sie kümmern sich um die Zählung ist jetzt, Sie können die
select_for_update
option verwiesen wird, die von Emil Stenstrom. Hier ist was, das aussieht wie:Dieser liest den aktuellen Wert aus und sperrt die entsprechenden Zeilen bis zum Ende der Transaktion. Jetzt ist nur noch ein Arbeiter, der Lesen kann, zu einer Zeit. Sehen die docs für mehr auf select_for_update.
InformationsquelleAutor der Antwort Xephryous
Django 1.7
InformationsquelleAutor der Antwort derevo
Oder wenn Sie wollen einfach nur einen Zähler und nicht ein persistentes Objekt, das Sie verwenden können, itertools Zähler, der die Implementierung in C. Das GIL wird die Gewährleistung von Sicherheit erforderlich.
--Sai
InformationsquelleAutor der Antwort Sai Venkat