我已经将Django设置为在它们自己的线程中运行一些重复的任务,并且我注意到它们总是留下未完成的数据库连接进程(pgsql"事务中的空闲").

我查看了Postgres日志(log),发现事务没有完成(没有回滚).我try 在我的功能上使用各种事务装饰符,但没有成功.

我切换到手动事务管理,并手动执行回滚,这起作用了,但仍然使流程处于"空闲"状态.

因此,然后我调用connection.close(),一切都很正常.

但是我想知道,为什么Django的典型事务和连接管理不适用于这些从Django主线程派生的线程化任务?

推荐答案

经过数周的测试和阅读Django源代码,我找到了自己问题的答案:

Transactions

Django的默认自动提交行为仍然适用于我的线程化函数.然而,它在Django文件中写道:

一旦您执行了需要写入数据库的操作,Django就会生成INSERT/UPDATE/DELETE语句,然后执行COMMIT.没有隐式回滚.

最后一句话很直白.除非Django中的某些内容设置了脏标志,否则它不会发出回滚命令.因为我的函数只执行SELECT语句,所以它从未设置脏标志,也没有触发提交.

这与PostgreSQL认为事务需要回滚的事实相反,因为Django为时区发出了SET命令.在查看日志(log)时,我放弃了自己,因为我一直看到这些ROLLBACK语句,并假设Django的事务管理是来源.事实证明并非如此,这没什么大不了的.

Connections

连接管理是事情变得棘手的地方.原来Django使用signals.request_finished.connect(close_connection)来关闭它通常使用的数据库连接.因为在Django中通常没有不涉及请求的操作,所以您认为这种行为是理所当然的.

不过,在我的情况下,没有请求,因为作业(job)已经安排好了.没有请求意味着没有信号.无信号表示数据库连接从未关闭.

回到事务方面,结果发现,在事务管理没有任何更改的情况下,只需调用connection.close()就会在PostgreSQL日志(log)中发出我一直在寻找的ROLLBACK语句.

Solution

解决方案是允许正常的Django事务管理正常进行,并通过以下三种方式之一关闭连接:

  1. 编写一个decorator来关闭连接,并在其中封装必要的函数.
  2. 钩住现有的请求信号,让Django关闭连接.
  3. 在功能结束时手动关闭连接.

这三个人中的任何一个都会(并且确实)工作.

这让我疯狂了好几个星期.我希望这对其他人有帮助!

Database相关问答推荐

芭蕾舞女演员坚持 1:N 关系

使用 Npgsql 执行年龄查询并在 .NET 应用程序中返回结果?

如何在 N1QL 查询(Couchbase 查询)中使用 LENGTH() 字符串函数

如何在 ubuntu 中使用脚本添加带有连字符的数据库名称

PostgreSQL 参数化 Order By / Limit in table 函数

SQL Server 2008如何同步不同服务器中的数据库?

是否可以使用 Mongo 的 Object ID作为其唯一标识符?如果是这样,如何将其转换为字符串并按字符串查找?

当您达到 SQL Server Express 4GB / 10GB 限制时会发生什么?

我需要在这个 Django 模型中添加一个 db_index 吗?

应用程序用户应该是数据库用户吗?

SQL Server 2008 中的 Open Table go 了哪里?

不带 WHERE 子句的 UPDATE 查询

限制来自本地主机的 MySQL 连接以提高安全性

如何解析来自 Google 快讯的数据?

Spring data : CrudRepository 的保存方法和更新

是否有任何支持协议缓冲区的数据库?

数据库 - (行或记录、列或字段)?

我可以在 /sdcard 上下载 SQLite 数据库并从我的 Android 应用程序访问它吗?

最佳事件采购数据库策略

数据库事务是否防止竞争条件?