Случайные ошибки базы данных с Django 1.7, uwsgi и PostgreSQL

После обновления моего приложения Django 1.6 до Django 1.7 я начал получать случайные ошибки при извлечении данных из PostgreSQL:

DatabaseError: server sent data ("D" message) without prior row description ("T" message)
lost synchronization with server: got message type "�", length -1244613424

DatabaseError: lost synchronization with server: got message type "0", length 842674226

ProgrammingError: no results to fetch

ValueError: invalid literal for int() with base 10: 'feuj3f47jvsdv7tgnj43g63j'

Когда я быстро открываю 10 вкладок в браузере, половина вкладок загружается нормально, половина из них выдает ошибку БД. Когда я обновляю вкладки, где произошли ошибки, они загружаются нормально.

Я запускаю Django через uwsgi и nginx, версия psycopg2 2.5.4.

В целом похоже, что каким-то образом связь с Postgres полностью нарушена, и результаты разных запросов смешиваются.


Редактировать:

После нескольких часов устранения неполадок я обнаружил следующее:

Django 1.6 + uwsgi — работает
Django 1.7 + gunicorn — работает
Django 1.7 + uwsgi — не работает, выдает ошибки базы данных. Таким образом, проблема, похоже, связана именно с комбинацией uwsgi и Django 1.7. Что странно, у меня есть другой проект Django 1.7, работающий на том же сервере с тем же uwsgi, и у него нет проблем.

Любые идеи?

(Я не очень против перейти на гуникорн, наверное, придется идти по этому пути, но все же интересно, почему так происходит)


Обновление 2: более внимательное изучение показывает совершенно безумные вещи, происходящие внутри Django, например, первичный ключ модели заменяется текущим пользователем session_id (это источник ошибки «invalid literal for int() with base 10») и Django, выдающий запросы к БД, «забыв ", чтобы указать предложение WHERE. Я бы, наверное, назвал это каким-то повреждением памяти.


Обновление 3: мы перешли с uwsgi на gunicorn, и теперь проблемы исчезли. Все отлично работает. Я, вероятно, все еще ищу правильное решение, хотя.


person Spc_555    schedule 09.10.2014    source источник
comment
libpq не соответствует psycopg2? Это что-то низкоуровневое, в psycopg2 или в libpq, во всяком случае.   -  person Craig Ringer    schedule 09.10.2014
comment
Мои старые (производство Django 1.6) и новые (разработка Django 1.7) установки используют один и тот же сервер, поэтому я не понимаю, как у одного могут быть проблемы с lipbq, а у другого нет.   -  person Spc_555    schedule 09.10.2014
comment
Но вы правы, возможно psycopg2 неправильно настроен при компиляции, надо проверить   -  person Spc_555    schedule 09.10.2014
comment
Ну, похоже проблема как-то с самим Django, смотрите обновление.   -  person Spc_555    schedule 09.10.2014
comment
как у вас работает uWSGI? многопоточность или многопроцессорность (или и то, и другое)?   -  person roberto    schedule 09.10.2014
comment
@roberto однопоточный, многопроцессный (кстати, я пытался ограничить количество процессов до 1, это не имеет значения)   -  person Spc_555    schedule 09.10.2014
comment
просто из-за паранойи: вы уверены, что не используете супер старую сломанную версию uWSGI? (как и все ‹ 1.2.8)   -  person roberto    schedule 14.10.2014
comment
@Roberto да, я уверен. Я попытался установить последнюю выпущенную версию из pypi и из текущей основной ветки GitHub, обе показывают одинаковые результаты.   -  person Spc_555    schedule 14.10.2014


Ответы (1)


Я думаю, что lazy-apps=true должен помочь. Из документации uwsgi:

uWSGI пытается (ab) использовать семантику копирования при записи вызова fork(), когда это возможно. По умолчанию он будет разветвляться после загрузки ваших приложений, чтобы разделить как можно больше их памяти. Если такое поведение по какой-то причине нежелательно, используйте опцию lazy-apps. Это даст указание uWSGI загружать приложения после fork() каждого рабочего процесса. Остерегайтесь, так как есть более старые варианты, называемые ленивыми, которые являются более инвазивными и крайне обескураживающими (они все еще здесь только для обратной совместимости).

Если вы не включите lazy-apps, воркеры будут совместно использовать память и, скорее всего, испортят ее:

первичный ключ модели заменяется session_id текущего пользователя.

Когда дело доходит до соединений и прочего, не устанавливать lazy-apps опасно.

Недостатком является то, что каждый работник будет иметь полный пул соединений (если пул соединений имеет место), и вы можете в конечном итоге использовать много соединений.

Я не эксперт по python, но я думаю, что можно использовать что-то вроде gevent для централизованной обработки пула соединений. Тогда вам может даже не понадобиться lazy-apps.

person judu    schedule 27.03.2015
comment
Сейчас у меня нет времени проверять эту идею, но звучит правдоподобно. - person Spc_555; 12.05.2015