代码之家  ›  专栏  ›  技术社区  ›  Gabriel Hurley

线程化Django任务不会自动处理事务或数据库连接?

  •  52
  • Gabriel Hurley  · 技术社区  · 17 年前

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

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

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

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

    1 回复  |  直到 17 年前
        1
  •  111
  •   Gabriel Hurley    17 年前

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

    交易

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

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

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

    连接

    连接管理是事情变得棘手的地方。事实证明Django使用 signals.request_finished.connect(close_connection) 关闭它通常使用的数据库连接。由于Django中通常不会发生不涉及请求的事情,因此您认为这种行为是理所当然的。

    connection.close()

    解决方案

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

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

    这三个人中的任何一个都会(并且会)起作用。

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