python 多进程/进程池死锁(数据库)

背景

    使用python进程池模块时代码卡死(死锁),且使用多进程过程中未涉及进程通信,此外多线程、单进程运行良好。

问题查询

   经反复运行,调试,查看日志(过程痛不欲生,不与过多赘述,说多了都是泪),发现卡死都是在数据库执行语句上。

问题锁定

    经上,可以锁定问题在多进程与数据库链接上

    进程池部分代码如下,使用Django orm:

    

from multiprocessing import Pool
from dateutil.relativedelta import relativedelta
from django.conf import settings
from django import db

def produce_mistake(start_date, end_date):
    start_date_str = start_date.strftime('%Y年%m月%d日')
    end_date_str = (end_date - relativedelta(days=1)).strftime('%Y年%m月%d日')
    mistake_name = u'%s至%s错题集' % (start_date_str.decode('utf-8'), end_date_str.decode('utf-8'))
    subject_dict = settings.SUBJECT_CHOICES
    subject_ids = subject_dict.keys()
    mistake_id = "%s-%s" % (start_date.strftime("%Y%m%d"), end_date.strftime("%Y%m%d"))
    mistake, is_new = Mistake.objects.get_or_create(
        mistake_id=mistake_id,
        mistake_type='1',
        defaults={'start_datetime': start_date,
                  'end_datetime': end_date,
                  'mistake_name': mistake_name}
    )
    # db.close_old_connections()
    page_num = 1
    school_data_list = []
    while True:
        school_list = AccountApiHandler.get_school_list(page_num=page_num)
        if not school_list:
            break
        for school_data in school_list:
            school_data_list.append(school_data)
        page_num += 1
    multiprocessing_pool = Pool()
    for school_data in school_data_list:
        multiprocessing_pool.apply_async(mistake_main,
                                         (school_data, subject_ids, mistake.id, start_date, end_date))
    multiprocessing_pool.close()
    logger.info(u'错题集:%s等待所有进程结束!' % mistake_name)
    multiprocessing_pool.join()

    代码中主进程调用了 get_or_create方法与数据库建立通信,此时,通过Pool模块fork创建子进程,子进程会复制一份主进程的内容,那么所有的子进程都会使用主进程的数据库连接池访问数据库,此时便会造成死锁

解决方式:

    在创建子进程前,关闭主进程数据库连接池即可,将上面代码注释部分解开即可

    db.close_old_connections()   #关闭数据库链接

相关链接:https://blog.csdn.net/xhy1994/article/details/87029427

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页