Python 线程化Django任务不';是否自动处理事务或数据库连接?

Python 线程化Django任务不';是否自动处理事务或数据库连接?,python,database,django,multithreading,transactions,Python,Database,Django,Multithreading,Transactions,我已经将Django设置为在它们自己的线程中运行一些重复性任务,并且我注意到它们总是留下未完成的数据库连接进程(pgsql“事务中空闲”) 我查看了Postgres日志,发现事务没有完成(没有回滚)。我尝试在我的函数上使用各种事务装饰器,但没有成功 我切换到手动事务管理并手动执行回滚,这很有效,但仍然让流程处于“空闲”状态 然后我调用了connection.close(),一切正常 但我仍在想,为什么Django的典型事务和连接管理不能用于这些从Django主线程派生的线程任务呢?经过几周的测试

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

我查看了Postgres日志,发现事务没有完成(没有回滚)。我尝试在我的函数上使用各种事务装饰器,但没有成功

我切换到手动事务管理并手动执行回滚,这很有效,但仍然让流程处于“空闲”状态

然后我调用了connection.close(),一切正常


但我仍在想,为什么Django的典型事务和连接管理不能用于这些从Django主线程派生的线程任务呢?

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

交易

Django的默认自动提交行为对于我的线程函数仍然适用。但是,它在Django文件中指出:

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

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

这与PostgreSQL认为事务需要回滚的事实背道而驰,因为Django为时区发出了SET命令。在查看日志时,我放弃了,因为我一直看到这些回滚语句,并假设Django的事务管理是源代码。结果不是这样,没关系

连接

连接管理是事情变得棘手的地方。Django使用
信号。request\u finished.connect(close\u connection)
关闭它通常使用的数据库连接。由于Django中通常不会发生不涉及请求的事情,因此您认为这种行为是理所当然的

但是,在我的例子中,没有请求,因为作业已安排。没有请求就意味着没有信号。无信号表示数据库连接从未关闭

回到事务,事实证明,在没有对事务管理进行任何更改的情况下,只要调用
connection.close()
,就会在PostgreSQL日志中发出我一直在寻找的ROLLBACK语句

解决方案

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

  • 编写一个decorator,关闭连接并在其中封装必要的函数
  • 钩住现有的请求信号,让Django关闭连接
  • 在功能结束时手动关闭连接
  • 这三个人中的任何一个都会(并且会)起作用


    这已经让我发疯好几个星期了。我希望这对其他人有帮助

    很高兴你终于解决了这个问题。这并不明显。我想知道在文档中的某个地方添加注释是否值得。这张票据描述了一个非常类似的问题:很好的解释,谢谢你的时间和努力,Gabriel!