Nasıl herhangi bir önbelleğe ve yeniden veri görmezden Django zorla mı?
Bir HTTP isteği olarak adlandırılan bir süreçten Django veritabanı modelleri kullanıyorum. Bu işlem yeni bir veri birkaç saniyede yoklamak ve biraz da işlem yapmak gerekiyordu. Birkaç saniye boyunca uyur ve sonra veritabanından tüm işlenmemiş veri alır bir döngü var.
Gördüklerim ilk getir sonra işlem asla yeni bir bilgi görür. Bir kaç test yaptım ve Django yeni QuerySets her zaman bina olmama rağmen sonuçları önbelleğe alma gibi görünüyor. Bunu doğrulamak için, bir Python kabuğundan yaptım:
>>> MyModel.objects.count()
885
# (Here I added some more data from another process.)
>>> MyModel.objects.count()
885
>>> MyModel.objects.update()
0
>>> MyModel.objects.count()
1025
Gördüğünüz gibi, yeni bir veri sonucu değiştirmez ekleme Kont. Ancak, yöneticinin güncelleme arama() yöntem sorunu çözmek gibi görünüyor.
Bu güncelleştirme herhangi bir belge bulamıyorum() yöntemi ve ne yaptığını hiçbir fikrim yok.
Benim sorum, neden Django docs söylediklerine ters olan bu davranış önbellekleme, görüyorum. Ve nasıl olmasını engellemek mi?
CEVAP
Bu sorunu vardı ve bunun için iki kesin çözüm buldum bir tane cevap gönderme değer düşündüm.
Bu MySQL varsayılan işlem modu ile ilgili bir sorun. Django varsayılan olarak değişiklikler veritabanında yapılan Göremezsiniz bu da demek oluyor ki başlangıçta bir işlem açar.
Bu gibi göstermek
Terminal 1'de django bir kabuk çalıştırın
>>> MyModel.objects.get(id=1).my_field
u'old'
Ve başka bir terminal 2'de
>>> MyModel.objects.get(id=1).my_field
u'old'
>>> a = MyModel.objects.get(id=1)
>>> a.my_field = "NEW"
>>> a.save()
>>> MyModel.objects.get(id=1).my_field
u'NEW'
>>>
Terminal 1'e geri sorun göstermek için - biz hala veritabanından eski değeri okuyun.
>>> MyModel.objects.get(id=1).my_field
u'old'
Şimdi terminal 1'de çözüm göstermek
>>> from django.db import transaction
>>>
>>> @transaction.commit_manually
... def flush_transaction():
... transaction.commit()
...
>>> MyModel.objects.get(id=1).my_field
u'old'
>>> flush_transaction()
>>> MyModel.objects.get(id=1).my_field
u'NEW'
>>>
Yeni veri okunur
Burada kütüphane ile kolay yapıştırmak için bir blok içinde kod
from django.db import transaction
@transaction.commit_manually
def flush_transaction():
"""
Flush the current transaction so we don't read stale data
Use in long running processes to make sure fresh data is read from
the database. This is a problem with MySQL and the default
transaction mode. You can fix it by setting
"transaction-isolation = READ-COMMITTED" in my.cnf or by calling
this function at the appropriate moment
"""
transaction.commit()
Alternatif çözüm benim değiştirmektir.MySQL için set varsayılan işlem modunu değiştirmek için
transaction-isolation = READ-COMMITTED
Mysql için nispeten yeni bir özelliktir ve 25 ** olduğunu unutmayın. Ayrıca eğer istersen django bağlantı giriş kısmında bu koyabilirsiniz.
3 yıl sonra güncelleme
Django 1.6 26 ** şimdi bu artık bir sorun. Yukarıdaki örnekte şimdi MySQL REPEATABLE-READ
(varsayılan) olup olmadığını flush_transaction()
kod READ-COMMITTED
işlem yalıtım modu olmadan gayet iyi çalışıyor.
Sigara otomatik yürütme modu koştu Django önceki sürümlerinde neler olduğunu select
ilk deyimi bir işlem açması oldu. Beri MySQL varsayılan modu REPEATABLE-READ
Bu demektir güncellemeleri veritabanı okunacak sonraki select
açıklamaları da bu yüzden gerek flush_transaction()
kod yukarıda ki durur hareket ve yeni bir tane başlatır.
Hala READ-COMMITTED
hareket yalıtım olsa kullanmak isteyebilirsiniz nedenleri vardır. Bir işlem terminal 1 koyduğunuz ve terminalden yazar görmek istiyorsan 2 READ-COMMITTED
gerekir.
flush_transaction()
kod şimdi bir admin bunu kaldırmak tavsiye ederim Django 1.6 uyarı üretir.
Model alan Güney kullanarak yeniden ad...
Nasıl Veri türü güvenli olun ve yenide...
Herhangi bir veri kaybı olmadan bir ta...
Nasıl bir veri tek bir sütunu yeniden ...
Nasıl önbellek veya yeniden yükleme Si...