Django大文件夹压缩后MySQL连接超时问题求助
问题原因分析
你的压缩任务最长耗时48小时,远超过Django配置的CONN_MAX_AGE(25分钟)和MySQL的wait_timeout(8小时),任务执行期间数据库连接早已被MySQL主动关闭。之前的方法无效主要有几个核心原因:
close_old_connections()仅处理当前线程的连接,若压缩任务在独立线程/进程中执行,主线程调用该方法无法清理任务线程的旧连接;且该方法仅回收超过CONN_MAX_AGE的连接,无法识别已被MySQL主动关闭的失效连接。- 遍历
connections.all()若未主动触发重新连接,Django执行ORM操作时可能仍从连接池中复用残留的失效连接。
彻底解决方法
1. 数据库操作前强制重建连接
在执行ExportStatus更新的代码块中,彻底关闭当前线程所有连接并主动重建:
from django.db import connections def update_export_status(export_id, package_size, zip_time): # 遍历所有数据库连接,强制关闭并重建 for conn in connections.all(): conn.close() conn.connect() # 执行更新操作 ExportStatus.objects.filter(id=export_id).update( package_size=package_size, zip_time=zip_time )
2. 异步任务场景的连接管理优化
如果压缩任务通过Celery等异步框架执行,需在任务启动和数据库操作前两次重置连接:
from celery import shared_task from django.db import connections @shared_task def compress_folder_task(export_id, folder_path): # 任务启动时先清理旧连接,避免后续复用失效连接 for conn in connections.all(): conn.close() # 执行压缩逻辑(耗时48小时的操作) package_size, zip_time = perform_large_compression(folder_path) # 更新前再次重置并重建连接 for conn in connections.all(): conn.close() conn.connect() ExportStatus.objects.filter(id=export_id).update( package_size=package_size, zip_time=zip_time )
3. 辅助配置优化
- 调整
CONN_MAX_AGE至小于MySQLwait_timeout的值(比如设为3600秒),让Django主动回收旧连接:
# settings.py DATABASES = { 'default': { # 其他数据库配置 'CONN_MAX_AGE': 3600, 'OPTIONS': { # 启用MySQL自动重连作为辅助机制 'init_command': 'SET AUTO_RECONNECT=1', } } }
内容的提问来源于stack exchange,提问作者Ajay Banstola
相关产品推荐
相关产品推荐

