Code

Opened 8 years ago

Closed 7 years ago

#2829 closed defect (invalid)

I can't clear what looks like a Model-level DB cache

Reported by: plesur@… Owned by: adrian
Component: Database layer (models, ORM) Version: master
Severity: critical Keywords: windows mysql
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

It looks like my models are caching their DB query in a way that I can't clear.

If I call "Model.objects.all()" and then make any changes to the DB with my MySQL client, the results of subsequent Model.objects.all() invocations never changes.

Example, with model PendingAlert:

PendingAlert.objects.all()

[<PendingAlert: PendingAlert object>, <PendingAlert: PendingAlert object>]

(...now, in mysql...)
mysql> delete from pending_alert;
Query OK, 2 rows affected (0.00 sec)

(...now, back in my Django session)

PendingAlert.objects.all()

[<PendingAlert: PendingAlert object>, <PendingAlert: PendingAlert object>]

...I just verified - the first Django session never clears its cache even if I alter the pending_alert table using Django instead of straight in MySQL.

Just to make sure that I have the right mental model here: Isn't Model.objects.all() supposed to create a QuerySet with its own search? Shouldn't these calls be touching the database directly?

Attachments (0)

Change History (6)

comment:1 Changed 8 years ago by mtredinnick

There is no model-level cache or anything like that involved here.

My guess would be that there is an uncommitted transaction floating around somewhere that means the deletes haven't really hit the database. I'll leave this open for now, pending a bit more thinking, but I strongly suspect it's not a Django bug.

comment:2 Changed 8 years ago by plesur@…

Just to add some more data: This definitely isn't an uncommitted transaction. The deletes hit the database, other clients see them, and if I quit my Django process and restart it then it sees the deletes (...but doesn't see any further changes until it's quit and restarted again).

comment:3 Changed 7 years ago by Simon G. <dev@…>

  • Keywords PendingAlert added
  • Resolution set to worksforme
  • Status changed from new to closed

Resolving as worksforme unless the reporter or anyone else is still having this issue.

comment:4 follow-up: Changed 7 years ago by ejot <magnus@…>

  • Resolution worksforme deleted
  • Status changed from closed to reopened
  • Version set to SVN

Im also having this issue. Running on svn rev 5637 (did a fresh checkout to test) and MySQL 5.0.41-commynity-nt, all on Windows.

list(Entry.objects.all())
... list of Entry objects
Perform an insert via MySQL commandline client
list(Entry.objects.all())
... same list of objects returned

Had a fellow in #django try the same thing, using sqlite, and he got an updated list returned.

comment:5 in reply to: ↑ 4 Changed 7 years ago by anonymous

  • Component changed from Admin interface to Database wrapper
  • Keywords windows mysql added; PendingAlert removed

Tried using the same django setup as I have on Windows on my debian system and running the same tests... a new list is returned here.

Linux abaddon 2.6.18-4-686 #1 SMP Mon Mar 26 17:17:36 UTC 2007 i686 GNU/Linux
MySQL 5.0.32-Debian-7etch1-log

These is my first attempt ever submitting tickets so I hope Im doing this right :)

Replying to ejot <magnus@derelik.net>:

Im also having this issue. Running on svn rev 5637 (did a fresh checkout to test) and MySQL 5.0.41-commynity-nt, all on Windows.

list(Entry.objects.all())
... list of Entry objects
Perform an insert via MySQL commandline client
list(Entry.objects.all())
... same list of objects returned

Had a fellow in #django try the same thing, using sqlite, and he got an updated list returned.

comment:6 Changed 7 years ago by Simon G. <dev@…>

  • Resolution set to invalid
  • Status changed from reopened to closed

Hmm... I can't replicate this. I'm running OSX, MySQL 5.0.45. Here's what I've done:

In [1]: from t2829.models import *

In [2]: all = two829.objects.all()

In [3]: all
Out[3]: [<1:hello>, <2:fudge>]


# Ok - right here, I open another terminal to a MySQL command prompt, and execute this:
# INSERT INTO t2829_two829 (var1) VALUES ('spork');
# there are now 3 records. 

In [4]: all = two829.objects.all()

In [5]: all
Out[5]: [<1:hello>, <2:fudge>, <3:spork>]

I'm getting the correct answer, and the same happens if I update/delete from within the MySQL client. Are you using MyISAM tables (I am) or InnoDB tables? This may be an outcome of some mysql-level query cache, but I know that if anything changes in a MyISAM table, then the qcache goes, but this might not be the same for InnoDB.

Please - try this out, and see if you can recreate it. Here's the model I've used:

from django.db import models

# Create your models here.
class two829(models.Model):
    var1 = models.CharField(maxlength=20)
    
    def __repr__(self):
        return '<%d:%s>' % (self.id, self.var1)


    class Admin:
        pass

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.