2012-05-17 4 views
4

My django app сохраняет модели django в удаленной базе данных. Иногда сейвы взрывоопасны. Чтобы освободить основной поток (* thread_A *) приложения от времени, затрачиваемого на сохранение нескольких объектов в базе данных, я подумал о переносе объектов модели в отдельный поток (* thread_B *) с помощью collections.deque и иметь * thread_B * сохраняйте их последовательно.Python GIL: блокировка django save()?

Однако я не уверен относительно этой схемы. save() возвращает идентификатор новой записи базы данных, поэтому он «заканчивается» только после ответа базы данных, которая находится в конце транзакции.

ли django.db.models.Model.save() действительно блокировать GIL -wise и освободить другой Пайтон резьбы во по сделке?

+0

Планируете ли вы получить доступ к базе данных из любого другого потока во время 'save()'? –

+0

@DonalFellows В моем конкретном случае - не локально. Возможно, какой-то удаленный наблюдатель может запросить базу данных, но это обычное использование транзакций базы данных. – Jonathan

+0

[Представление Дэвида Бизли в 2011 году Pycon GIL] (http://www.dabeaz.com/talks/EmbraceGIL/EmbracingGIL.pdf) выглядит актуальным – Jonathan

ответ

7

Django's save() не делает ничего особенного для GIL. На самом деле, с GIL в коде Python почти ничего нельзя сделать - когда он выполняется, поток должен содержать GIL.

Есть только два способа, которыми GIL могли бы получить выпущенные в save():

  • Python решает переключения потоков (после sys.getcheckinterval() инструкции)
  • Джанго вызывает интерфейс базы данных процедуру, которая реализуется, чтобы освободить GIL

Второй момент может быть тем, что вы ищете - выполняется SQL COMMIT, и во время этого выполнения база данных SQL выпускает GIL. Однако это зависит от интерфейса SQL, и я не уверен, действительно ли популярные выпуски GIL *.

Кроме того, save() делает намного больше, чем просто работает несколько UPDATE/INSERT заявлений и COMMIT; он делает много бухгалтерии в Python, где он должен держать GIL. В общем, я не уверен, что вы получите что-нибудь от перемещения save() в другой поток.


UPDATE: Глядя на источниках, я узнал, что и sqlite модуля и psycopg выпустите GIL, когда они звонят подпрограммы баз данных, и я думаю, что другие интерфейсы делают то же самое.

+0

Не звонки I/O освобождают GIL? Нужно ли быть явным? – ubik

+1

Да, да. Рутины, написанные на C, не выпускают GIL автоматически, но автор явно должен это делать. См. Http://docs.python.org/c-api/init.html?highlight=gil#releasing-the-gil-from-extension-code –

+0

Ah OK, я предполагал, что интерфейс SQL написан на Python. – ubik

-4

Я думаю, что python не блокирует ничего сам по себе, но база данных делает.

+2

Знаете ли вы, что такое GIL? http://en.wikipedia.org/wiki/Global_Interpreter_Lock – NPE

+0

база данных удалена таким образом по IP-соединению, поэтому я не уверен, что вы имеете в виду, она не может блокировать соединение, вопрос в том, что происходит локально – Jonathan

+0

Да, я знаю, что такое GIL, но Django не использует потоки, и я думаю, что он не использует GIL. – Denis

2

Как правило, вы никогда не должны беспокоиться о потоках в приложении Django. Если вы обслуживаете приложение с помощью Apache, gunicorn или почти любого другого сервера, кроме сервера разработки, сервер будет порождать несколько процессов и полностью уклоняться от GIL. Исключение составляет то, что вы используете gunicorn с gevent, и в этом случае в этих процессах будет много процессов, но также и microthreads - в этом случае параллелизм помогает немного, но вам не нужно самостоятельно управлять потоками того, что. Единственный случай, когда вам нужно беспокоиться о GIL, - это если вы пытаетесь создать несколько потоков для обработки одного запроса, что обычно не является хорошей идеей.

Метод Django save() не освобождает сам GIL, но бэкэнд базы данных будет (в большинстве случаев основная часть времени, затраченного на save(), будет делать ввод/вывод базы данных). Тем не менее, почти невозможно правильно воспользоваться этим в хорошо разработанном веб-приложении.Ответы на ваш взгляд должны быть быстрыми даже в том случае, если они выполняются синхронно - если они делают слишком много работы, чтобы быть быстрыми, то используйте задержанную работу с сельдереем или другим мастером задания, чтобы завершить дополнительную работу. Если вы попытаетесь пометить свое мнение, вам нужно будет закончить этот поток перед отправкой ответа клиенту, который в большинстве случаев ничего не поможет и просто добавит дополнительные накладные расходы.

+0

Моя система не является веб-приложением. Я использую django исключительно для ORM, никакого веб-сервера не задействован – Jonathan

+0

Хм, я вижу. Ну, если вы много работаете в python (время процессора за пределами доступа к БД), вы можете использовать библиотеку многопроцессорности или просто запустить несколько процессов, что я и делаю с моими сценариями, использующими Django для ORM (мой занять несколько дней, чтобы работать даже с несколькими процессами). Но если вы используете потоки, они могут по крайней мере мультиплексировать операции ввода-вывода в базе данных, потому что фактический блокирующий ввод-вывод приведет к выпуску GIL. –