Django ORM在Postgres DB上留下空闲连接

时间:2017-04-06 18:00:17

标签: django postgresql database-connection django-orm

最近,由于数据库连接错误,我的Django应用程序经常崩溃:

OperationalError: FATAL:  sorry, too many clients already

当我进入app数据库时,我发现确实有近100个打开的连接,都有相同的查询(由Django ORM执行),并且都处于idle状态。

我一直在手动做SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle';,但我很困惑为何会发生这种情况。任何人都可以对这里发生的事情有所了解吗?

我的Django数据库设置不会偏离默认值(我没有定义CONN_MAX_AGE或任何性质的东西)。

是什么导致这个?我没有做任何高级Django查询。这可以通过Django设置或者某些PostgreSQL配置来解决吗?任何建议都表示赞赏。

3 个答案:

答案 0 :(得分:3)

显然你没有断开连接。查询完成后使用db.close_connection()会有所帮助。另外如果我把它弄好CONN_MAX_AGE到一些短的值可能有帮助。并考虑使用一些会话池,例如pgbouncer用于django连接。这样,如果你有太多的连接,它将等待(或重复使用以前,取决于配置)而不是中止执行错误...

更新:解释我为何提出建议

from docs

  

每个线程都维护自己的连接,您的数据库必须支持   至少与工作线程一样多的同时连接。

因此,如果你有更多线程,那么postgres max_connections,你会得到提到的错误。如果CONN_MAX_AGE尚未通过,则每个线程都可以重用连接。您的设置为0,因此在查询完成后应该关闭连接,但是您看到100个空闲连接。所以他们没有结束。大量的连接意味着它们也不会被重用(逻辑:如果你有100个并行查询,它们就不会全部空闲,如果你有这么多,它们就不会被重用 - 打开新的)。所以我认为django不会像宣传的那样关闭它们 - 所以CONN_MAX_AGE设置为0在你的代码中不起作用。因此,我建议使用db.close_connection()强制断开连接,并将CONN_MAX_AGE设置为某个较小的值可以改变行为。

答案 1 :(得分:2)

最好的猜测没有更多的细节,但如果它是相同的查询,并且它们都是空闲的,感觉就像你正在进行某种异步编程,并且你遇到了僵局,特别是你的僵局正在显现数据库连接本身已经饱和。

答案 2 :(得分:0)

如果您尚未定义CONN_MAX_AGE并且您没有使用任何第三方池 - 那么这必须是您的代码或您正在使用的库中的某个问题。默认情况下,Django会打开并关闭每个请求的数据库连接。你在pg_stat_activity中看到空闲连接的事实并不意味着存在死锁 - 相反,它意味着某些东西已经打开了这些连接并且没有关闭它。

我首先要确定这些连接是否实际来自Django,例如重新启动应用并了解它如何影响pg_stat_activity。如果你确认了,那么检查你是否没有混合任何留下悬空线程/进程的异步或多处理代码。