4

我的 django 应用程序将 django 模型保存到远程数据库。有时扑救是突发的。为了将应用程序的主线程 (*thread_A*) 从将多个对象保存到数据库的时间成本中解放出来,我想将模型对象转移到一个单独的线程 (*thread_B*)collections.deque并使用 *thread_B* 保存他们依次。

但是我不确定这个计划。save()返回新数据库条目的 id,因此它仅在数据库响应后“结束”,即事务结束。

django.db.models.Model.save()真的会阻塞GIL并在事务期间释放其他 python 线程吗?

4

3 回答 3

7

Djangosave()对 GIL 没有什么特别之处。事实上,在 Python 代码中你几乎不能用 GIL 做任何事情——当它被执行时,线程必须持有 GIL。

GIL 的发布方式只有两种save()

  • Python 决定切换线程(根据sys.getcheckinterval()指令)
  • Django 调用一个数据库接口例程,实现该例程以释放 GIL

第二点可能是您正在寻找的——执行 SQLCOMMIT并在执行期间,SQL 后端释放 GIL。但是,这取决于 SQL 接口,我不确定流行的是否真的发布了 GIL*。

此外,save()不仅仅是运行几条UPDATE/INSERT语句和一个COMMIT; 它在 Python 中做了大量的簿记工作,它必须保存 GIL。总之,我不确定您是否会从转移save()到不同的线程中获得任何收益。


更新:通过查看源代码,我了解到sqlite模块和psycopg在调用数据库例程时都会释放 GIL,我猜其他接口也是如此。

于 2012-05-17T07:55:13.400 回答
3

通常,您不必担心 Django 应用程序中的线程。如果您使用 Apache、gunicorn 或除开发服务器之外的几乎任何其他服务器为您的应用程序提供服务,那么该服务器将产生多个进程并完全避开 GIL。例外情况是,如果您将 gunicorn 与 gevent 一起使用,在这种情况下,将有多个进程,但这些进程中还有微线程——在这种情况下,并发会有所帮助,但您不必自己管理线程即可利用那个。唯一需要担心 GIL 的情况是,如果您尝试生成多个线程来处理单个请求,这通常不是一个好主意。

Django save() 方法不会释放 GIL 本身,但数据库后端会(在大多数情况下,save() 花费的大部分时间将用于数据库 I/O)。但是,在设计良好的 Web 应用程序中正确利用这一点几乎是不可能的。即使同步完成,您的视图中的响应也应该很快——如果他们做的工作太多而不能很快,那么使用 Celery 或其他任务主管的延迟工作来完成额外的工作。如果您尝试在视图中进行线程化,则必须在向客户端发送响应之前完成该线程,这在大多数情况下无济于事,只会增加额外的开销。

于 2012-05-17T16:37:51.893 回答
-4

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

于 2012-05-17T07:17:14.517 回答