Django迁移的查询仍在运行中。

4
我正在开发一个Django Web应用程序,并注意到一些奇怪的事情。 以下查询将在数据库中保持执行状态。

SELECT "django_migrations"."app", "django_migrations"."name" FROM "django_migrations"

这里是来自pg_stat_activity的示例:select query_start,state_change,waiting,state,query from pg_stat_activity;
test6=> select query_start,state_change,waiting,state,query from pg_stat_activity;
          query_start          |         state_change          | waiting | state  |                                                                  query
-------------------------------+-------------------------------+---------+--------+--------------------------------------------------------------------------------------------------
 2017-06-21 16:02:21.926337+02 | 2017-06-21 16:02:21.926402+02 | f       | idle   | SELECT "django_migrations"."app", "django_migrations"."name" FROM "django_migrations"

直到停止"runserver"

当前设置:

  • Django 1.11.2
  • PostgreSQL 9.2.17
  • 仅使用Django ORM
  • 所有迁移都已应用
  • 在settings.py中设置了CONN_MAX_AGE

为什么Django在查询执行后不关闭连接?


你说查询还在运行,是什么意思?你是如何判断的?首先你是如何运行它的? - Daniel Roseman
通过 "pg_stat_activity"。查询仍处于 "空闲" 状态,连接在 10/15 小时后仍然保持活动状态。 - Mattia
1个回答

4
文档中可以看出,Django使用持久连接:

[...] 每个线程维护自己的连接

runserver命令本身就是一个线程,SELECT "django_migrations"."app", "django_migrations"."name" FROM "django_migrations"只是表示连接上最后进行的查询,一旦结果返回,状态就变为空闲。
如果您尝试在检查迁移后执行查询,例如在wsgi中,该请求将替换您当前正在查看的请求。 因此,默认情况下,runserver为每个传入请求创建一个线程,因此用于检查迁移的连接(在主线程中)永远不会关闭,根据文档:

在每个请求的开头,Django会关闭连接,如果它达到了最大年龄。 如果您的数据库在一段时间后终止空闲连接,您应将CONN_MAX_AGE设置为较低的值,以便Django不会尝试使用已被数据库服务器终止的连接。(这个问题可能只影响非常低的流量站点。)

正如您所读到的,PostgreSQL或Django都可以在下一个请求时关闭连接。因此,您要么配置PostgreSQL以关闭空闲连接,要么在runserver上使用--nothreading以重用主线程建立的连接(警告:它会严重影响性能)。

谢谢您的回复,但是为什么我将“CONN_MAX_AGE”设置为5秒后连接仍然保持打开状态呢? - Mattia
我添加了这部分内容,并解释了为什么第一个连接要保留与runserver一起使用。 - SebCorbin
感谢您的回复,我可能误解了CONN_MAX_AGE的工作原理。我可能会使用from django.db import close_old_connections close_old_connections()来管理自动关闭连接的自动任务。谢谢。 - Mattia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接