Подтвердить что ты не робот

Задача Threaded Django автоматически не обрабатывает транзакции или соединения db?

У меня Django настроен для запуска некоторых повторяющихся задач в их собственных потоках, и я заметил, что они всегда оставляют незавершенные процессы подключения к базе данных (pgsql "Idle In Transaction" ).

Я просмотрел журналы Postgres и обнаружил, что транзакции не были завершены (без ROLLBACK). Я пытался использовать различные декодеры транзакций для своих функций, не повезло.

Я переключился на ручное управление транзакциями и выполнил откат вручную, который сработал, но все же оставил процессы как "Idle".

Итак, я назвал connection.close(), и все хорошо.

Но мне не интересно, почему не работает типичное управление транзакциями и подключением Django для этих многопоточных задач, которые генерируются из основного потока Django?

4b9b3361

Ответ 1

После нескольких недель тестирования и чтения исходного кода Django я нашел ответ на свой вопрос:

Сделки

По умолчанию автозаполнение по умолчанию Django по-прежнему сохраняется для моей потоковой функции. Однако в документах Django указано:

Как только вы выполните действие, которое необходимо записать в базу данных, Django создает инструкции INSERT/UPDATE/DELETE, а затем выполняет COMMIT. Theres не подразумевается ROLLBACK.

Последнее предложение очень буквально. Он НЕ выдает команду ROLLBACK, если только что-то в Django не установило грязный флаг. Поскольку моя функция выполняла только инструкции SELECT, она никогда не устанавливала грязный флаг и не вызывала COMMIT.

Это противоречит факту, что PostgreSQL считает, что транзакция требует ROLLBACK, потому что Django выпустил команду SET для часового пояса. При просмотре журналов я отбросил себя, потому что я продолжал видеть эти инструкции ROLLBACK и предполагал, что управление транзакциями Django является источником. Оказывается, это не так, и это нормально.

Подключения

Управление соединениями - это то, где вещи становятся сложными. Оказывается, Django использует signals.request_finished.connect(close_connection) для закрытия подключения к базе данных, которое обычно использует. Поскольку в Django обычно не происходит ничего, что не связано с запросом, вы принимаете это поведение как должное.

В моем случае, однако, запроса не было, потому что задание было запланировано. Никакой запрос не означает никакого сигнала. Нет сигнала означает, что соединение с базой данных не было закрыто.

Возвращаясь к транзакциям, выясняется, что простое обращение к connection.close() при отсутствии каких-либо изменений в управлении транзакциями вызывает оператор ROLLBACK в журнале PostgreSQL, который я искал.

Решение

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

  • Напишите декоратор, который закрывает соединение и завершает в нем необходимые функции.
  • Захватите существующие сигналы запроса, чтобы Django закрыл соединение.
  • Закройте соединение вручную в конце функции.

Любой из этих трех будет (и работает).

Это сбило меня с ума в течение нескольких недель. Надеюсь, это поможет кому-то еще в будущем!