2010-05-26 19 views
2

我有django应用程序,通过fastcgi在lighttpd下运行。 FCGI运行脚本如下所示:Django多进程问题

python manage.py runfcgi socket=<path>/main.socket 
    method=prefork \                          
    pidfile=<path>/server.pid \                                   
    minspare=5 maxspare=10 maxchildren=10 maxrequests=500 \ 

我使用SQLite。所以我有10个进程,它们都使用同一个数据库。接下来我有两个观点:

def view1(request) 
    ... 
    obj = MyModel.objects.get_or_create(id=1) 
    obj.param1 = <some value> 
    obj.save() 

def view2(request) 
    ... 
    obj = MyModel.objects.get_or_create(id=1) 
    obj.param2 = <some value> 
    obj.save() 

,如果这个观点在两个不同的线程执行,有时我得到为MyModel例如在DB与ID = 1和更新或者参数1或参数2(但不能同时) - 这取决于其过程是第一个。 (当然在现实生活中ID变化,但有时2个进程使用相同的ID执行这两个视图)

问题是:我应该怎么做更新param1和param2的实例?我需要一些东西来合并不同进程中的更改。

一个决定是创建进程间锁定的对象,但在这种情况下,我会得到顺序执行的意见,他们将不能够同时执行,所以我要求帮助

DUPE的Django: How can I protect against concurrent modification of data base entries

+2

SQLite通常被认为不适合作为测试环境之外的后端;迁移到PostgreSQL或MySQL将成为阻力最小的路径。 – 2010-05-26 18:21:40

+1

[Django:如何防止数据库条目的并发修改]的可能重复(http://stackoverflow.com/questions/320096/django-how-can-i-protect-against-concurrent-modification-of-数据库条目) – 2010-05-26 18:23:46

+0

嗯...可能是这个讨论可以是有用的。我可以在我的模型中添加时间戳字段并在保存前更新它。成功更新意味着没有其他线程/进程没有改变我的对象,所以我可以调用save方法。但是,如果更新失败,这意味着其他线程或进程已经改变了它,我应该从数据库重新获取并尝试合并更改。我对吗? P.S:但是很奇怪,Django对解决这些问题没有任何帮助......所有的开发人员都可以发明自己的解决方案吗?这很奇怪 – iKiR 2010-05-27 05:41:18

回答

1

的SQLite如果您需要对数据库进行并发访问,这不是一个好的选择。 我建议切换到一些其他RDBMS,例如MySQL或PostgreSQL, 并且还考虑到get_or_create脆性:

How do I deal with this race condition in django?

关于上述链接,也有第二解决这一问题 - 使用READ COMMITED隔离级别,而不是REPEATABLE READ。但是它没有经过测试(至少在MySQL中),所以可能会有更多的错误/问题。

+0

谢谢你的回复。 嗯......这个问题在MySQL或PostgreSQL中是如何解决的?关于get_or_create - 我读过这个问题,并且我自己实现了get_or_create(通过继承管理器),在这个实现中我调用超级实现这个方法,如果它引发了IntegrityError,我接收它,提交事务并再次调用get_or_create。 你能告诉我如何在SQLite中使用READ COMMITED隔离级别? – iKiR 2010-05-27 03:40:14

+0

我不认为SQLite实现传统意义上的隔离级别:http://www.sqlite.org/sharedcache.html,但我可能是错的。不过,如果你想在concurent环境中使用SQLite,那么更好的做法是为不可避免的OperationalErrors做准备。 – 2010-05-27 09:08:39