【发布时间】:2019-12-04 07:02:15
【问题描述】:
我正在使用ThreadPoolExecutor 来加快数据处理速度。问题是线程池创建了新的数据库连接,而 Django 并没有关闭它们。我在settings.py 中确实有 CONN_MAX_AGE,并且我已经尝试致电django.db.close_old_connections()。
这是一个代码示例:
def compute(job):
result = FooModel.objects.filter(...).aggregate(...)
return BarModel.objects.create(result)
def process(dataset):
thread_pool = ThreadPoolExecutor(max_workers=20)
futures = []
for job in dataset:
futures += [thread_pool.submit(compute, job)]
results = list(r.result() for r in wait(futures)[0])
return results
for i in range(0, 100):
process(['foo', 'bar', 'qux'])
如果空闲数据库连接是在另一个线程中启动的,Django ORM 是否能够终止它们?
更新: 有趣的是,Django 甚至不知道这些连接:
>>> from django.db import connections
>>> print(len(connections.all()))
>>> 2
mypostgresdb=# select count(*) from pg_stat_activity;
count
-------
182
(1 row)
而且所有工作线程肯定已经关闭:
>>> # workers threads were closed:
>>> import threading
>>> threading.enumerate()
[<_MainThread(MainThread, started 140660203321088)>]
【问题讨论】:
-
这有什么更新吗?
-
@Dougyfresh 我没有找到解决方案。解决方法是只创建一次
ThreadPoolExecutor(例如,不要在循环中多次创建它),因此额外的数据库连接不超过 20 个。 -
刚刚添加了我作为答案创建的解决方法。
-
来自this report,
ThreadPoolExecutor不会重用线程。它已在 Python 3.8 中修复。我认为这可能是 CONN_MAX_AGE > 0 时连接泄漏的原因,因为 django 查询将在新线程中运行,这将导致打开新连接。我目前使用 Python 3.7.7 并且有类似的问题。
标签: python django multithreading postgresql threadpool