2012-05-07 38 views
0

我有一个模型(PurchaseOrder - 缩写PO)持有时间预算。用户可以将小时记录添加到此预算中,其中每个小时记录可减少剩余预算。Django 1.1信号 - 线程奇怪的时间问题

我实施了更新剩余预算的信号。增加一小时记录后,预算相应减少。由于计算可能非常耗时,因此我使用了一个线程来执行此任务。

def update_po_remaining_value(sender, instance, **kwargs): 
    CalculatePOThread(sender, instance).start() 
post_save.connect(update_po_remaining_value, sender=HourRecord)  
post_delete.connect(update_po_remaining_value, sender=HourRecord) 

线程CalculatePOThread通过获取小时记录集,并在扣除总小时记录从预算

hr_set = HourRecord.objects.filter(purchase_order = po) 

在我dev.workspace这工作完全正常设置计算剩余PO预算值。在生产post_save连接也工作正常,但我遇到post_delete信号一个奇怪的问题。经常发生的情况是,查询HourRecord.objects.filter(purchase_order = po)返回的小时记录总数仍包含已触发CalculatePOThread线程的已删除小时记录。

无论如何,我在执行查询之前,在线程中添加了6秒的延迟,从而避免了这种行为。 time.sleep(6)。

有没有人知道为什么会出现这种情况?看起来post_delete信号在记录真正从数据库中删除之前被触发..!?但是,这将是Django中的一个错误,这将是我最后的猜测。

回答

1

很难说,但我的猜测会是你遇到了线程安全问题。当你创建一个线程来处理一个长时间运行的任务时,你必须意识到,当它试图完成时,一个类似的线程可以很容易地被解雇,并且负责相同的任务。通常,在使用线程时,您希望保持足迹最小化,换句话说,不要使它们高度依赖数据库状态等。

如果数据库访问必需的,在这种情况下,您需要设置锁定以防止数据库同时混淆。鉴于您正在运行Django 1.1,这将变得更加困难。如何在Django 1.1中实现表级锁定将取决于您正在运行的数据库服务器并保证自己的问题。

+0

感谢您的回答。一个额外的信息:我确信我是唯一一个在prod.env中搞乱的人。并且只是一个一个地触发 - post.delete信号。因此,我确信没有其他线程与我的测试冲突。因此,应该通过对象删除命令设置锁定,并且只应在释放锁定/删除对象之后触发post_delete信号。但我猜这是Django内部的东西,我无法影响。 PS:DB = postgres,webserver = apache。 –

+0

好像这个问题也在这里讨论:http://groups.google.com/group/django-haystack/browse_thread/thread/c452da9acfc04c64?pli=1 –