2012-05-17 57 views
4

我的django应用程序将django模型保存到远程数据库。有时节省是突然的。为了将应用程序的主线程(* thread_A *)从保存多个对象到数据库的时间间隔中解放出来,我考虑使用collections.deque将模型对象传送到一个单独的线程(* thread_B *)并且* thread_B *按顺序保存它们。Python GIL:是django save()阻塞?

但我不确定这个计划。 save()返回新数据库条目的ID,所以它只有在数据库响应后才会“结束”,这是在事务结束时。

是否真的django.db.models.Model.save()阻止GIL -wise并在交易释放其他的Python线程

+0

您是否打算在'save()'过程中从任何其他线程访问数据库? –

+0

@DonalFellows在我的具体情况 - 不是本地。一些远程观察者当然可以查询数据库,但这是正常的数据库事务使用。 – Jonathan

+0

[David Beazley's 2011 Pycon GIL presentation](http://www.dabeaz.com/talks/EmbraceGIL/EmbracingGIL.pdf)看起来相关 – Jonathan

回答

7

Django的save()对GIL没有任何特别之处。事实上,在Python代码中几乎没有什么可以用GIL来完成 - 当它被执行时,线程必须保存GIL。

只有两种方式GIL可以在save()得到释放:

  • Python的决定切换线程(后sys.getcheckinterval()指令)
  • Django的调用实现释放GIL
  • 数据库接口程序

第二点可能是您正在查找的内容 - 执行SQL COMMIT,并在执行期间,SQL后端释放GIL。但是,这取决于SQL接口,我不确定流行的实际上是否释放了GIL *。

此外,save()做了很多不仅仅是运行几个UPDATE/INSERT陈述和COMMIT;它在Python中做了很多簿记,它必须持有GIL。总之,我不确定你会从save()到另一个线程获得什么。


UPDATE:从寻找来源,我了解到,无论是sqlite模块和psycopg做释放GIL时,他们呼吁数据库例程,我想其他的接口做同样的。

+0

不要I/O调用释放GIL吗?它真的需要明确吗? – ubik

+1

是的,它的确如此。用C编写的例程不会自动释放GIL,但作者明确必须这样做。请参阅http://docs.python.org/c-api/init.html?highlight=gil#releasing-the-gil-from-extension-code –

+0

好的,我假设SQL接口是用Python编写的。 – ubik

-4

我认为python不会自己锁定任何东西,但数据库呢。

+2

你知道GIL是什么吗? http://en.wikipedia.org/wiki/Global_Interpreter_Lock – NPE

+0

数据库是远程因此通过IP连接,因此我不知道你的意思,它不能阻止连接,问题是本地发生了什么 – Jonathan

+0

是的,我知道什么是GIL,但Django不使用线程,我认为它不使用GIL。 – Denis

2

通常,您不应该担心Django应用程序中的线程。如果您使用Apache,gunicorn或几乎任何其他服务器为开发服务器提供服务,服务器将产生多个进程并完全逃避GIL。例外情况是,如果您使用gevent来使用gunicorn,在这种情况下会有多个进程,但在这些进程中也会有微线程 - 在这种情况下,并发性会有所帮助,但您不必自己管理线程以利用那个。唯一需要担心GIL的情况是,如果您尝试产生多个线程来处理单个请求,这通常不是一个好主意。 Django save()方法不会释放GIL本身,但数据库后端将(在大多数情况下save()中花费的大部分时间将执行数据库I/O)。但是,在设计良好的Web应用程序中正确利用这一点几乎是不可能的。即使在同步完成后,您的观点应该会很快 - 如果他们做了太多的工作以便快速完成工作,那么请与Celery或其他任务管理员一起延期完成额外工作。如果您尝试在视图中进行线索处理,则必须在向客户端发送响应之前完成该线程,而在大多数情况下,这对客户端无任何帮助,只会增加额外开销。

+0

我的系统不是一个Web应用程序。我使用django纯粹是为了ORM,没有涉及网络服务器 – Jonathan

+0

嗯,我明白了。那么,如果你在python中进行了很多处理(在数据库访问之外的CPU时间),那么你可以使用多处理库或者启动多个进程,这就是我使用Django进行ORM的脚本(我的即使使用多个进程也需要花费数天时间)。但是如果你使用线程,他们至少可以在数据库I/O操作上复用,因为实际的阻塞I/O将释放GIL。 –