Python 从另一个进程保存对象时,在Model.objects.filter()之后需要Django transaction.commit()

Python 从另一个进程保存对象时,在Model.objects.filter()之后需要Django transaction.commit(),python,mysql,django,multiprocessing,Python,Mysql,Django,Multiprocessing,我有两个进程运行Django代码库,出于各种原因,一个进程将更新对象,如下所示: myObj.aField = "updated" myObj.save() def getObj(xxx): objs = TheModel.objects.filter(xyz=xxx) for obj in objs: print obj.aField 随后,另一个进程尝试读取该对象,如下所示: myObj.aField = "updated" myObj.save() def g

我有两个进程运行Django代码库,出于各种原因,一个进程将更新对象,如下所示:

myObj.aField = "updated"
myObj.save()
def getObj(xxx):
   objs = TheModel.objects.filter(xyz=xxx)
   for obj in objs:
      print obj.aField
随后,另一个进程尝试读取该对象,如下所示:

myObj.aField = "updated"
myObj.save()
def getObj(xxx):
   objs = TheModel.objects.filter(xyz=xxx)
   for obj in objs:
      print obj.aField
从第二个进程读取值时,我不会看到更新的值,而是看到旧值。第二次运行函数时,我确实看到了变化

我注意到,如果从第二个过程(一次读取)开始,我按如下方式更改函数,则得到更新的值:

@transaction.commit_manually
def getObj(xxx):
    objs = TheModel.objects.filter(xyz=xxx)
    transaction.commit()
    for obj in objs:
        print obj.aField
在手动添加decorator
@transaction.commit\u
transaction.commit()
行(位于
filter()
调用的正下方)之后,我确实从字段中获得了更新后的值(该值是从另一个进程保存的)

有什么理由需要这样做吗?使用
transaction.commit()
对一个实际上根本不更新模型的函数有什么影响/潜在问题? 我不知道它为什么会起作用,也不知道它是否有意义,所以希望有其他人遇到了这个问题


谢谢,

我也遇到了这个问题。Django缓存查询结果(对于单个进程来说这是一件好事)。如果第二个进程具有相同查询的缓存,则在刷新缓存之前,它不会看到更新


出于某种原因,
transaction.commit()
会刷新缓存,因此有助于解决此问题。在运行查询之前调用该方法,您应该可以直接从数据库中看到结果。

因为您使用的是事务中间件,所以每个请求都会获得不同的事务

处理Web请求中的事务的推荐方法是通过Django的TransactionMiddleware将它们绑定到请求和响应阶段

它是这样工作的:当一个请求启动时,Django启动一个事务。如果生成的响应没有问题,Django将提交任何挂起的事务。如果view函数产生异常,Django将回滚所有挂起的事务


这意味着,如果第二个进程的请求在写入触发之前进入,则其事务将在写入之前进行。然后,数据库将做正确的事情,并报告在创建第二个进程的事务时的当前值。在读取之前手动提交第二个进程的事务是无害的(只要它没有进行任何编辑),并告诉数据库创建一个新事务。它将更新写入的日期,从而提供修改后的结果。

您使用的是哪个版本的Django?您使用的是Django的事务中间件吗?Django 1.5,是的,我使用的是事务中间件:Django 1.6中引入了Autocommit。显然,他们意识到了这一问题的根源。如果您愿意,可以在早期版本中启用自动提交,这不是默认设置。因此,如果启用自动提交,所有这些问题都会神奇地消失?运行它有什么缺点吗?它比缓存更复杂。另一个进程几乎肯定有一个在数据库更改之前就已打开的事务,因此不会更新内存中的Python对象。数据库正在(正确地)返回读取进程原始事务的值。Peter:如果是,那么我如何才能“修复它”?:)我尝试在第一段代码(保存模型实例的代码)上添加decorator并运行transaction.commit(),但很有可能这并没有改变第二个进程的任何内容。需要提交的不是编写进程。请参阅我的答案以获得完整的解释-基本上,数据库是为了保护您在阅读过程开始后不会更改您的状态。我看到1.6删除了“推荐方式”文本,并且不推荐使用事务管理,而支持
原子\u请求