python - How do I force Django to ignore any caches and reload data? -
I am using a Django database model from a request that is not asked by the HTTP request. This process should be voted for new data every few seconds and some processing should be done about it. I have a loop that sleeps for a few seconds and then receives all uncontrolled data from the database.
The one I see is that after getting it first, the process never sees any new data. I have run some tests and it seems that the Django result is caching, even if I am creating a new query set every time. To verify it, I did it by opening a Python:
gt; & Gt; MyModel.objects.count () 885 # (Here I've added some more figures from the second process.)> Gt; & Gt; & Gt; MyModel.objects.count () 885 & gt; & Gt; & Gt; MyModel.objects.update () 0 & gt; & Gt; & Gt; MyModel.objects.count () 1025
As you can see, adding new data does not change the result count. However, when calling the update () method of the manager, it seems to fix the problem.
I do not find any documentation on that update method and I do not know what else it can do.
My question is, why am I seeing this caching behavior, what does that say? And how do I stop it from happening?
Having this problem and getting two fixed solutions for it. I think this is worth to post another answer. .
This is a problem with MySQL default transaction mode. Django opens a transaction initially, which means that by default you will not see changes made in the database.
Perform such a way
Run a detox shell in Terminal 1
& gt; & Gt; & Gt; MyModel.objects.get (id = 1) .my_field u'old '
and second in Terminal 2
& gt; & Gt; & Gt; MyModel.objects.get (id = 1) .my_field u'old '& gt; & Gt; & Gt; A = MyModel.objects.get (id = 1) & gt; & Gt; & Gt; A.my_field = "NEW"> gt; & Gt; & Gt; A.save ()> gt; & Gt; & Gt; MyModel.objects.get (id = 1) .my_field u'NEW '& gt; & Gt; & Gt;
Back to Terminal 1 to display the problem - we still read the old values from the database.
& gt; & Gt; & Gt; MyModel.objects.get (id = 1) .my_field u'old '
Now display 1 solution in the terminal
& gt; & Gt; & Gt; By Django.db import transaction & gt; & Gt; & Gt; & Gt; & Gt; & Gt; @ Transaction.commit_manually ... def flush_transaction (): ... transaction.commit () ... & gt; & Gt; & Gt; MyModel.objects.get (id = 1) .my_field u'old '& gt; & Gt; & Gt; Flush_transaction ()> gt; & Gt; & Gt; MyModel.objects.get (id = 1) .my_field u'NEW '& gt; & Gt; & Gt;
New data is now read
Here is a code that is easy to paste blocks with dosstring
Django.db import transaction @ transaction.commit_manually def flush_transaction (): "" "Flush the current transaction so that we can not read stale data, use it in long-running processes to read the latest data from the database This is MySQL and the default transaction mode. You can set it in my.cnf by setting "transaction-isolation = READ-COMMITTED" Or this function can be corrected by calling at appropriate time "transaction.commit ()
The alternative solution is to replace my.cnf for MySQL to replace the original transaction mode
transaction-isolation = read-coded
Note that this is a relatively new feature for MySql and if you wish, Can be put in the preamble.
Update after 3 years
Now when Django 1.6 does not have any problems at all. Now the above example works fine without code flush_transaction ()
code if your MySQL iter-read
(default) or has been read
Transaction is in isolation mode
The first select
statement opened a transaction what was happening in previous versions of the DJ that was running in non-autocommit mode. Since the default mode of MySQL is iterated read
it means that any updates to the database will be read later by the select
statement - hence the flush_transaction ()
/ Code> Code which prevents transactions and initiates a new one.
There are still reasons that you want to use the READ-COMMITTED
transaction segregation. If you were to put Terminal 1 in the transaction and you wanted to see it from Terminal 2, then you would need READ-COMMITTED
.
The flush_transaction ()
code now creates an exclusion warning in Django 1.6, so I recommend you remove it.
Comments
Post a Comment