SORU
27 Temmuz 2010, Salı


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
17 EKİM 2011, PAZARTESİ


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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • FF Radio

    FF Radio

    16 Mayıs 2008
  • Chriselle Lim

    Chriselle Li

    26 Ocak 2008
  • Peyton

    Peyton

    28 Aralık 2008