django是否在查询之间缓存模型数据?

时间:2014-09-05 14:54:40

标签: django caching django-models race-condition

我正在使用django 1.6,使用mysql 5.6作为innodb表的数据库。在我的设置文件中将Debug设置为false。

在脚本中,我遍历一个元素列表,检查它是否已存在于db中,如果它不存在则创建,如下所示:

for item in list:
    try:
        MyModel.objects.get(field=item)
    except MyModel.DoesNotExist:
        MyModel.objects.create(field=item)

我希望这只在不存在的情况下在数据库中创建一个项目,但是这种方法会创建具有相同字段值的多个项目。这里似乎有某种缓存。

我在这里有两个问题;

如何在循环中每次运行时检查数据库的最新状态是否可以更改此行为?

这种行为是否与我通过脚本运行相关?如果在视图中运行相同的循环。这种行为会有什么不同吗?

编辑:

我已经提出了类似问题的建议,将事务隔离更改为READ-COMMITTED。这会导致常规Django视图操作中的性能缺陷吗?

2 个答案:

答案 0 :(得分:3)

好像你在这里遇到了竞争条件。如果你看看Django本身为你提供的get_or_create代码,它看起来与你的相似

try:
   obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
   obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
obj.save()

事实上,上面的代码也可能受到竞争条件的影响,并创建的对象多于documentation所说的对象:However, if uniqueness is not enforced at the database level for the kwargs used in a get_or_create call (see unique or unique_together), this method is prone to a race-condition which can result in multiple rows with the same parameters being inserted simultaneously.

因此,在这种情况下,解决方案是使field唯一。

或者,如果该字段不是唯一的,我建议您明确尝试使用transactions

from django.db import transaction 

with transaction.atomic():
    # do_database_stuff

答案 1 :(得分:1)

使字段唯一

#your model
class MyModel(models.Model):
      field = modesl.IntegerField(unique=True)

      def __unicode__(self):
          return '%s' % self.field


"""your code to interac with the model (Don't matther where you have this code 
(in the view, or elsewhere)), the behavior of the code is going to be the same. 
views.py just is a python file."""

from you_app.models import MyModel
from django.db import IntegrityError

def insert_item(list_item):
    for item in list_item:
        try:
            itemobj = MyModel.objects.create(field=item)
        except IntegrityError:
            #exists, posible you want to make some update here
            itemobj = MyModel.objects.get(field=item)
            #maybe update...
        else:
            #do whatevert you want with itemobj
            print itemobj