3

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

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

添加装饰器@transaction.commit_manually和调用transaction.commit()正下方的行后filter(),我确实从字段中获取了更新的值(从其他进程中保存。)

有什么理由需要这样做吗?transaction.commit()在实际上根本不更新模型的功能上使用的影响/潜在问题是什么?我不确定它为什么起作用,如果它有意义,所以希望其他人遇到这个问题。

谢谢,

4

2 回答 2

4

由于您使用的是事务中间件,因此每个请求都会获得不同的事务。

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

它是这样工作的:当一个请求开始时,Django 开始一个事务。如果生成的响应没有问题,Django 将提交任何未决事务。如果视图函数产生异常,Django 会回滚所有待处理的事务。

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

于 2013-08-20T20:29:27.007 回答
1

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

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

于 2013-08-20T20:17:26.947 回答