I am facing a very peculiar problem that even when I delete some rows, I can just get them back again in same transaction. I am running this under apache and mod_wsgi, database is mysql.
Edit:
I have created a sample app to test it out, so that I can be sure that none of my code is culprit.
I created a testapp with following code
models.py
import uuid
from django.db import models
class TestTable(models.Model):
id = models.CharField(max_length=36, primary_key=True)
name = models.CharField(max_length=50)
@classmethod
def get_row(cls, name):
return TestTable(id=str(uuid.uuid4()), name=name)
def __unicode__(self):
return u"%s[%s]"%(self.name, self.id)
views.py
import traceback
import time
from django.db import transaction
from django.http import HttpResponse
from testapp.models import TestTable
@transaction.commit_manually
def test_view(request):
time.sleep(1)
out = []
try:
# delete 3 rows
for row in TestTable.objects.all()[:3]:
ID=row.id
out.append("deleting %s"%row)
row.delete()
# check fi really deleted
try:
TestTable.objects.get(id=ID)
out.append("row not deleted?")
except TestTable.DoesNotExist,e:
out.append("row deleted.")
# create 5 rows
for i in range(5):
row = TestTable.get_row("row %s"%i)
row.save()
except Exception,e:
out.append("Error:%s"%traceback.format_exc())
transaction.rollback()
else:
transaction.commit()
return HttpResponse('\n'.join(out), 'text/text')
urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('testapp.views', (r'^test_bug$', 'test_view')
TestScript
import urllib2
from multiprocessing import Process
def get_data():
r = urllib2.urlopen("http://localhost:81/timeapp/test/test_bug")
print "---------"
print r.read()
if __name__ == "__main__":
for i in range(2):
p = Process(target=get_data)
p.start()
Output:
$ python test.py
---------
deleting row 1[3ad3a82e-830f-4540-8148-88479175ed5e]
row deleted.
deleting row 0[544462d1-8588-4a8c-a809-16a060054479]
row deleted.
deleting row 3[55d422f3-6c39-4c26-943a-1b4db498bf25]
row deleted.
---------
deleting row 1[3ad3a82e-830f-4540-8148-88479175ed5e]
row not deleted?
deleting row 0[544462d1-8588-4a8c-a809-16a060054479]
row not deleted?
deleting row 3[55d422f3-6c39-4c26-943a-1b4db498bf25]
row not deleted?
So my question is how come deleted row is again retrievable by TestTable.objects.get, also even if I sleep more in second call so that first call can commit code I still get deleted rows in second call.
Your problem fascinated me, so I spent quite a bit of time investigating it, and the only conclusion I can come up with is that it’s a bona fide bug in either python-MySQL or MySQL itself. Here’s what I tried:
I should note that I changed the code slightly so that instead of:
I had:
This made it slightly easier to debug, and did not affect the manifestation of the problem.
Firstly, Django’s caching is not to blame here. The queries to get the counts were issued, as can be seen in the MySQL logs (the 1 and 2 represent the two separate concurrent connections that get made):
And of course, any subsequent attempts at fetching the count after the session is closed show that the row was in fact deleted. Furthermore, logging the received SQL results in
django.db.models.sql.queryshows that theSELECT COUNTstatements immediately following theDELETEstatements in the second half of the above log in fact returned 1, instead of the 0 one would expect. I have no explanation for this.As far as I can tell, there are only two options available to get the functionality you want. I’ve verified that both of them work:
MaxClientsandThreadsPerChildto 1 (not a very practical option).