Потоковая задача Django не обрабатывает автоматически транзакции или соединения с БД?
У меня есть Django, настроенный для запуска некоторых повторяющихся задач в своих собственных потоках, и я заметил, что они всегда оставляют незавершенные процессы подключения к базе данных (pgsql "Idle In Transaction").
Я просмотрел журналы Postgres и обнаружил, что транзакции не были завершены (без отката). Я попытался использовать различные декораторы транзакций на своих функциях, не повезло.
я переключился на ручное управление транзакциями и сделал откат вручную, это сработало, но все же оставило процессы "простаивающими".
и тогда я вызвал соединение.закрыть (), и все хорошо.
но мне остается задаться вопросом, почему типичное управление транзакциями и соединениями Django не работает для этих потоковых задач, которые порождаются из основного потока Django?
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 продолжалось как обычно и просто закройте соединение одним из трех способов:
- написать декоратор, который закрывает соединение и обернуть необходимые функции в нем.
- подключитесь к существующим сигналам запроса, чтобы Django закрыл соединение.
- закрыть соединение вручную в конце функции.
любой из этих трех будет (и делать) работу.
это сводило меня с ума в течение нескольких недель. Я надеюсь, что это поможет кому-то еще в будущее!
Comments