Как обрабатывать базу данных многопроцессорной обработки Python concurrency, в частности, с django?

Итак, я пытаюсь написать приложение, которое использует django как свой ORM, так как ему нужно будет сделать некоторые за кулисами и простой в использовании интерфейс. Это основная функциональность будет обрабатывать данные, которые в базе данных, в высоко-процессорном процессе (в основном monte carlo simulations), и я хочу реализовать многопроцессорность, в частности, используя Pool (я получаю 4 процесса). В основном мой код работает примерно так: около 20 детей родителя:

assorted import statements to get the django environment in the script
from multiprocessing import Pool
from random import random
from time import sleep

def test(child):
    x=[]
    print child.id
    for i in range(100):
        print child.id, i
        x.append(child.parent.id) #just to hit the DB
    return x

if __name__ == '__main__':
    parent = Parent.objects.get(id=1)
    pool = Pool()
    results = []
    results = pool.map(test,parent.children.all())
    pool.close()
    pool.join()
    print results

С кодом как таковым я получаю прерывистый DatabaseError или PicklingError s. Первые обычно имеют форму "искаженная база данных" или "потерянное соединение с сервером MySQL", последние обычно "не могут рассортировать model.DoesNotExist". Они случайны, происходят с любым процессом, и, конечно, нет ничего плохого в самой БД. Если я устанавливаю pool = Pool(proccesses=1), тогда он запускается в одном потоке просто отлично. Я также использую различные инструкции для печати, чтобы убедиться, что большинство из них действительно запущено.

Я также менял test на:

def test(child):
    x=[]
    s= random()
    sleep(random())
    for i in range(100):
        x.append(child.parent.id)
    return x

Это просто делает каждую итерацию паузой менее секунды, прежде чем запускать, и делает все в порядке. Если я получу случайный интервал до примерно 500 мс, он начнет действовать. Итак, вероятно проблема concurrency, не так ли? Но только с 4 процессами. Мой вопрос заключается в том, как решить эту проблему, не дав больших дампов данных раньше времени? Я протестировал его как с SQLite, так и с MySQL, и у обоих есть проблемы с этим.

Ответ 1

Хорошо, поэтому я решил (с помощью друга), что проблема в том, что django использует одно и то же соединение с базой данных для всех процессов. Обычно, когда у вас есть параллельные запросы db, они либо находятся в одном потоке (в этом случае GIL запускается), либо они находятся в отдельных потоках, и в этом случае django создает разные соединения с базой данных. Но при многопроцессорности питон делает глубокие копии всего, поэтому он передает одно и то же соединение с базами данных с подпроцессами, а затем они наступают друг на друга, пока он не сломается.

Решение должно инициировать новое соединение db изнутри каждого подпроцесса (что относительно быстро).

from django import db
...
def sub_process():
    db.close_connection()
    #the rest of the sub_process' routines

#code that calls sub_process with the pool

Отправлялся вперед и назад от этой линии и не имел этой линии и определенно исправлял все.