2009-12-11 7 views
20

In meiner Django-Anwendung führe ich wiederholt dieselbe Abfrage in meiner Datenbank aus (z. B. alle 10 Sekunden). Ich erstellen dann eine MD5-Summe über das Abfrage-Set, das ich erhalte, und vergleiche das mit der MD5-Summe, die ich im vorherigen Lauf erstellt habe. Wenn beide gleich sind, haben sich die Daten nicht geändert und die Webseite muss nicht aktualisiert werden.Wie Django Query Cache zu deaktivieren?

Während ich dies tue, können sich die Daten in der DB ändern.

Die Abfrage gibt jedoch das gleiche Abfrage-Set zurück, anscheinend aufgrund query caching.

Wie kann ich den Abfragecache deaktivieren und die Abfrage explizit auf der DB ausführen?

+0

Mögliche Duplikat [Wie erzwinge ich Django alle Caches zu ignorieren und die Daten neu zu laden?] (Http://stackoverflow.com/questions/3346124/how-do-i-force- django-to-ignore-any-caches-and-reload-data) –

Antwort

41

Ich stieß auf Verhalten, das ich dachte, war eine Art von Caching, aber es stellte sich heraus, dass Datenbanktransaktionen mich täuschen.

hatte ich das Problem, dass in einem anderen Verfahren wurden Elemente in die Datenbank hinzugefügt werden, und ich wollte Fortschritt des anderen Prozesses überwachen, so öffnete ich eine django Schale und gab die folgenden:

>>> MyData.objects.count() 
74674 

>>> MyData.objects.count() 
74674 

Der Wert änderte sich nicht, obwohl er tatsächlich in der Datenbank enthalten war. Ich erkannte, dass zumindest mit der Art, wie ich MySQL hatte & django Setup, dass ich in einer Transaktion war und würde nur eine "Momentaufnahme" der Datenbank zu dem Zeitpunkt, als ich die Transaktion geöffnet.

Da mit Ansichten in Django, Autocommit-Verhalten definiert hatte, war dies in Ordnung für jede Ansicht nur einen Schnappschuss zu sehen, als das nächste Mal eine Ansicht aufgerufen wurde, wäre es in einer anderen Transaktion. Aber für einen Code, der nicht automatisch festgeschrieben wurde, werden keine Änderungen in der Datenbank angezeigt, mit Ausnahme der in dieser Transaktion vorgenommenen Änderungen.

Nur gedacht, ich würde diese Antwort für jeden werfen, der auf diese Situation kommen könnte.

zu lösen, verpflichtet Ihre Transaktion, die manuell wie dies getan werden kann:

>> from django.db import transaction 
>> transaction.enter_transaction_management() 
>> transaction.commit() # Whenever you want to see new data 
+2

Vielen Dank, ich habe genau dieses Verhalten bei der Ausführung eines Befehls, der eine Warteschlange überwacht und einige Ereignisse verarbeiten muss. Wenn dies passiert, würde der Prozessor keine Benutzer finden, die nach dem Start des Befehls – victorcampos

+1

A 'transaction.commit_unless_managed()' erstellt wurden hat auch für mich gearbeitet. –

+1

Perfekte Antwort auf ein Problem, das ich so oft in der Vergangenheit nervte! Danke vielmals. – Sarang

6

Der Link auf die Django-Dokumentation zur Verfügung stellen bedeutet, dass die folgenden: die

>>> queryset = Poll.objects.all() 
>>> print [p.headline for p in queryset] # Evaluate the query set. 
>>> print [p.pub_date for p in queryset] # Re-use the cache from the evaluation. 

verwendet die Abfrage-Cache, wie Sie den Zugriff auf:

>>> print [e.headline for e in Entry.objects.all()] 
>>> print [e.pub_date for e in Entry.objects.all()] 

zwei Anfragen an die Datenbank, während erstellt gleiche Bewertungsergebnisse.

9

Abfrage-Caching gilt nur innerhalb eines QuerySet. Mit anderen Worten, wenn Sie das gleiche Queryset-Objekt zweimal auswerten, funktioniert das Query-Caching. Aber wenn Sie alle 10 Sekunden eine Abfrage durchführen, geschieht dies vermutlich über einen Cron, der jedes Mal einen neuen Prozess hervorruft, so dass Django auf keinen Fall etwas zwischenspeichern kann.

Es ist möglich, dass der eigene Cache Ihrer Datenbank in Betrieb genommen wird, wenn Sie wiederholt genau die gleiche Abfrage ausführen. Sie sollten sich die Dokumentation Ihres DBMS ansehen, um zu sehen, wie Sie das richtig verwalten können.

+1

Auch wenn dies korrekt ist, beantwortet dies nicht die Frage, die eindeutig auf django queryset zeigt. Antwort von @kekoa entspricht der Frage von OP. – sberder

1

Vielen Dank für Ihre Antworten, Ihre Antworten ließen mich ein paar Schritte zurück und überdenken.

Um Caching auf einer DBMS-Ebene zu testen, ging ich von Django weg und verwendete ein Shell-Skript, das ich sowieso hatte, um Daten aus einer SQLite-Datenbank regelmäßig abzufragen, während ich Daten in einer zweiten Shell-Sitzung hinzufügte. Die neuen Daten wurden in den periodischen Abfragen angezeigt, direkt nachdem ich sie hinzugefügt hatte. Daher wurde hier kein Abfrage-Caching durchgeführt.

Dies verengt es bis zum Django Teil. Der Code involviert ist nicht sehr komplex und ein wenig Log-Ausgabe und eine Code-Überprüfung offenbarte das Problem: Die Abfrage verwendet, um das Abfrage-Set zur Erstellung der MD5-Summe verwendet wurde, hatte einen Fehler und war immer leer. Daher war die MD5-Summe immer gleich. Sah in der Tat aus wie ein zwischengespeichertes Ergebnis - Daten ändern sich, aber das Abfrage-Set bleibt gleich. Das Problem wurde in der Anwendung nicht angezeigt, da eine andere Abfrage verwendet wurde, um die dort angezeigten Daten abzurufen.

Lektion gelernt: Wenn Sie völlig verwirrt sind, machen Sie einen Schritt zurück und überdenken Sie Ihre Annahmen.

Danke nochmal! :-)

0

I 1.8 dieses Problem auf django Version erfüllt. Es gibt keine direkte Möglichkeit, dies zu tun, aber es gibt einige Möglichkeiten, das Abfrage-Set neu zu evaluieren und auszuführen, indem auf db statt auf den Cache zugegriffen wird. Ich fand es in Django Queryset Documentation

Ich benutzte eine von ihnen, um mein Problem zu behandeln. Es ist exists() Funktion von Suchanfragen. len() und repr() können ebenfalls verwendet werden. Sie haben auch für mich gearbeitet.

Beispiel

queryset = ModelClass.objects.filter(....) 
queryset.exists() 

#or len(queryset) 
#or repr(queryset) 

#Now queryset is re-evaluated.