Обновление моделей django с помощью многопроцессорного пула блокирует базу данных - PullRequest
0 голосов
/ 02 декабря 2018

Я использую Jupyter Notebook, чтобы играть с данными, которые я храню в django / postgres.Я инициализирую свой проект следующим образом:

sys.path.append('/srv/gr/prg')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'prg.settings')
if 'setup' in dir(django):
    django.setup()

Есть много отдельных процессов, которые обновляют данные, и я хотел многопоточность, чтобы ускорить процесс.Все работает хорошо, когда я делаю обновления в одном потоке или использую sqlite.

def extract_org_description(id):
    o = models.Organization.objects.get(pk=id)
    logging.info("Looking for description for %s" % o.symbol)
    try:
        content = open('/srv/data/%s.html' % o.symbol)
    except FileNotFoundError:
        logging.error("HTML file not found for %s" % o.symbol)
        return
    doc = BeautifulSoup(content, 'html.parser')
    desc = doc.select("#cr_description_mod > div.cr_expandBox > div.cr_description_full.cr_expand")
    if not desc or not desc[0]:
        logging.info("Cannot not find description for %s" % o.symbol)
        return
    o.description = desc[0].text
    o.save(update_fields=['description'])
    logging.info("Description for %s found" % o.symbol)
    return("done %s" % id)

И это не будет работать:

p = Pool(2)
result = p.map(extract_org_description, orgs)
print(result)

В большинстве случаев оно будет зависать до тех пор, пока я его не прерву, без какой-либо конкретной ошибки, иногда у postgres будет "Тамтранзакция уже выполняется ", иногда я вижу ошибку" Нет результатов для извлечения ".Играя с размером пула, я мог бы заставить его работать, возможно, один или два раза, но трудно определить, в чем именно проблема.

Я попытался изменить стратегию, выбрав объекты и сопоставив их с extract_org_description, чтовозьмите объект в качестве параметра (в отличие от выбора на основе ключей), но это работает не лучше.

Единственная мысль, которая у меня возникла, - это когда django пытается выполнить автокоммит, все отдельные обновления, включаяте, которые происходят в других потоках, находятся в той же области транзакции, и это вызывает проблему.Но я не понимаю, как это исправить в Django.

1 Ответ

0 голосов
/ 03 декабря 2018

Ваш вопрос включает в себя термины многопроцессорность и многопоточность , но важно понимать, что это разные способы достижения параллелизма.

Django имеет встроенную поддержкудля многопоточности создаст новое соединение с базой данных для каждого потока .Если вы переключитесь с многопроцессорной обработки на многопоточность, ваша проблема должна быть решена.

В многопроцессорной обработке весь процесс разветвляется, и у нового процесса будет то же соединение с базой данных, что и у старого.Это приводит к проблемам, с которыми вы сталкиваетесь, например, когда вы пытаетесь открыть новую транзакцию, если она уже была открыта в том же соединении с базой данных другим процессом.

Если вам действительно нужна многопроцессорная обработка вместомногопоточность, возможно есть решения.Например, этот ответ предлагает просто закрыть соединения с базой данных, заставив Django создать новые.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...