Потоковая задача Django не обрабатывает автоматически транзакции или соединения с БД?



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



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



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



и тогда я вызвал соединение.закрыть (), и все хорошо.



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

544   1  

1 ответ:

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

сделки

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

Как только вы выполняете действие, которое необходимо записать в базу данных, Django создает инструкции INSERT/UPDATE/DELETE, а затем выполняет фиксацию. Там нет неявного ОТМЕНА.

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

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

подключения

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

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

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

решение

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

  1. написать декоратор, который закрывает соединение и обернуть необходимые функции в нем.
  2. подключитесь к существующим сигналам запроса, чтобы Django закрыл соединение.
  3. закрыть соединение вручную в конце функции.

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

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

Comments

    Ничего не найдено.