Автономный web2py-DAL с Pyramid — запросы, потоки и память

Я создаю приложение на платформе Pyramid и хотел бы использовать с ним web2py-DAL. База данных, встроенная в Firebird, является предпочтительной.

Это прекрасно работает, пока я не попытаюсь асинхронно вызвать несколько представлений с одной веб-страницы. Различные ошибки, такие как «Неверное состояние курсора», «Неверная ссылка на курсор» или «Попытка повторного закрытия закрытого курсора», возникают из драйвера kinterbasdb, где sqlite просто ломается без каких-либо сообщений об ошибках и берет с собой python. Эти вызовы представлений не делают ничего, кроме простого чтения с помощью SELECT.

Это происходит в том случае, если корневая фабрика пирамиды возвращает один и тот же объект DAL при каждом запросе. Кажется, что потоки из разных запросов работают с одним и тем же объектом курсора, поэтому курсор закрывается, в то время как другой поток предполагает, что курсор находится здесь.

Если я создаю новый объект DAL для каждого запроса, у меня возникает другая проблема - каждое новое соединение по каждому запросу выделяет память, и эта память не освобождается. Таким образом, после нескольких запросов доцентов теряется несколько сотен МБ памяти.

К сожалению, Sqlalchemy не подходит для этого проекта.

Есть идеи?


person Gleb Sternharz    schedule 04.04.2011    source источник
comment
Почему вы не используете полную версию сервера в этой веб-среде? Встроенный означает, что это будет работать в процессе, каждый из которых будет иметь монопольный доступ к базе данных. ИМХО, это объясняет, почему все работает, пока два разных запроса не заставят сервер пытаться открыть базу данных одновременно. То же самое произойдет, если второй запрос придет от другого клиента, в то время как сервер все еще обрабатывает первый.   -  person jachguate    schedule 04.04.2011
comment
Вам лучше задать этот вопрос непосредственно в списке рассылки web2py.   -  person Graham Dumpleton    schedule 05.04.2011
comment
@jachguate Проблема не в firebird - все проблемы остаются, если я тоже использую серверную версию. Я обнаружил, что объект DAL нельзя совместно использовать в потоках. Я мог бы создать новый объект DAL в начале каждого потока и закрыть его после. Теперь вопрос - где заканчивается поток запросов пирамиды? Где правильное место для удаления объекта DAL? Другой вариант - создать стек для запросов к базе данных, а затем передать запросы к базе данных объекту DAL из одного потока... @Graham-Dumpleton Верно. Или Пирамида. Я опубликую свое решение здесь, если оно там.   -  person Gleb Sternharz    schedule 05.04.2011


Ответы (2)


Дело в том, что объект DAL должен создаваться при каждом запросе. Но после этого его нужно закрыть вручную.

Я сделал это так: есть

request.add_finished_callback

свойство объекта запроса, поэтому я расширил объект DAL таким образом:

class Root(DAL):
    def __init__(self, request, uri):
        DAL.__init__(self, uri, pool_size=0)
        request.add_finished_callback(self._close)

    def _close(self, request):
        self._adapter.close_all_instances('commit')

Затем root_factory возвращает новый объект Root по каждому запросу.

Спасибо группе пользователей web2py!

person Gleb Sternharz    schedule 06.04.2011

Некоторые решения из списка рассылки web2py.

person Anthony    schedule 06.04.2011
comment
Да! Я разместил вопрос там несколько часов назад, и теперь уже есть очень полезные подходы. Группа web2py-users великолепна. - person Gleb Sternharz; 06.04.2011