Вопрос по multithreading, transactions, python, gil, django – Python GIL: блокирует ли django save ()?

4

Мое приложение django сохраняет модели django в удаленной базе данных. Иногда сейвы взрывные. Чтобы освободить основной поток (* thread_A *) приложения от времени сохранения нескольких объектов в базе данных, я подумал о переносе объектов модели в отдельный поток (* thread_B *), используяcollections.deque и * thread_B * сохранить их последовательно.

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

Does django.db.models.Model.save() really block GILи освободить другие потоки Pythonduring перевод?

collections.deque потокобезопасен(RTM) Jonathan
Планируете ли вы получить доступ к базе данных из любого другого потока во времяsave()? Donal Fellows
@DonalFellows В моем конкретном случае - не локально. Конечно, некоторый удаленный наблюдатель может запрашивать базу данных, но это обычное использование транзакции базы данных. Jonathan
являетсяcollections.deque потокобезопасный?threading.Queue кажется, лучше подходит для этой работы. ubik
David Beazley's 2011 Pycon GIL presentation выглядит актуально Jonathan

Ваш Ответ

3   ответа
7

Джанго & APOS; ssave() не делает ничего особенного с GIL. На самом деле вряд ли можно что-либо сделать с GIL в коде Python - когда он выполняется, поток должен содержать GIL.

Есть только два способа выпуска GIL вsave():

Python decides to switch threads (after sys.getcheckinterval() instructions) Django calls a database interface routine that is implemented to release the GIL

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

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

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

Разве звонки ввода-вывода не освобождают GIL? Это действительно должно быть явным?
Спасибо за правильный ответ. Я хочу добавить еще одну вещь, которая вызвала проблему в моем сценарии [Django + mysql], db.close () db.autoCommit (True)
Да, это так. Процедуры, написанные на C, не высвобождают GIL автоматически, но автору явно необходимо это сделать. Увидетьdocs.python.org/c-api/…
Ах, хорошо, я предполагал, что интерфейс SQL был написан на Python.
3

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

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

Моя система не является веб-приложением. Я использую django исключительно для ORM, веб-сервер не задействован Jonathan
МММ ясно. Что ж, если вы выполняете большую часть обработки в python (время ЦП вне доступа к БД), вы можете использовать многопроцессорную библиотеку или просто запустить несколько процессов, что я и делаю со своими сценариями, использующими Django для ORM (мой занять дни, чтобы работать даже с несколькими процессами). Но если вы используете потоки, они могут по крайней мере мультиплексировать операции ввода-вывода базы данных, потому что фактическая блокировка ввода-вывода высвободит GIL.
-4

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

Django использует базу данных. Так это на самом деле конкретный вопрос бэкэнда? Jonathan
Django работает с psycopg2 в качестве бэкэнда Postgres и psycopg не может объединяться в потоки, такие как база данных, когда вы запускаете wtite для блокировки таблицы, и потоки не имеют смысла.
Вы знаете, что такое GIL?en.wikipedia.org/wiki/Global_Interpreter_Lock
база данных удалена, таким образом, через IP-соединение, поэтому я не уверен, что вы имеете в виду, она не может блокировать соединение, вопрос в том, что происходит локально Jonathan
Да, я знаю, что такое GIL, но Django не использует потоки, и я думаю, что он не использует GIL.

Похожие вопросы