Должен ли я минимизировать использование db_session в Pony ORM? - PullRequest
1 голос
/ 14 марта 2019

Мне интересно, должен ли я минимизировать использование db_session или нет?Давайте рассмотрим эти два эквивалентных примера:

A)

def do_stuff():
    with db_session:
        task = orm.make_proxy(Task.select().first())
        task.mark_started()
    ...
    this_function_might_take_a_long_time(task)
    ...
    with db_session:
        task.mark_done()

B)

@db_session
def do_stuff():
    task = Task.select().first()
    task.mark_started()
    commit()
    ...
    this_function_might_take_a_long_time(task)
    ...
    task.mark_done()

Из прочтения документации я могу сказать, что Pony непоощрять микроуправление db_sessions

With this code each of view function you will define will be wrapped with db_session so you should not care about them.

Однако здесь предполагает, что его открытие может стоить стоимости (РЕДАКТИРОВАТЬ: это не 't, прочитайте ответ)

Before sending the first query, Pony gets a database connection from the connection pool.

Правильно ли я сказать, что что-либо за пределами B является преждевременной оптимизацией, и A следует рассматривать только в сценариях с ограниченным числом подключений к БД?

1 Ответ

1 голос
/ 15 марта 2019

Pony ORM автор Александр Козловский @metaprogrammer ответил на это в Официальном чате Pony ORM Telegram .


Цель db_session - управлять тремя вещами:

Подключение к базе данных

Пони связывает отдельное соединение с каждым потоком. Если процесс не использует потоки, будет использоваться только одно соединение. Когда db_session заканчивается, он возвращает свое соединение с пулом соединений. Это означает, что соединение остается открытым и сохраняется для будущего использования. Далее db_session будет использовать то же соединение. Таким образом, в отношении использования соединения нет разницы между одной db_session и несколькими последовательными db_sessions

Состояние транзакции

Когда db_session заканчивается, он выполняет неявную фиксацию. Нет никакой разницы между неявной и явной фиксацией, поэтому, если у вас есть одна db_session с ручным вызовом commit (), то это то же самое, что и несколько последовательных db_sessions. Однако, если вы не используете явный commit (), то long db_session может удерживать блокировку базы данных и мешать другим процессам работать с базой данных или конкретной таблицей, пока не будет выполнена фиксация

Кэш в памяти загруженных объектов

Основное различие между одним db_session и несколькими последовательными db_sessions заключается в управлении кэшем в памяти объектов, загружаемых из базы данных. Каждая db_session имеет отдельный кеш. Объекты внутри кеша сшиты отношениями. Если вы загружаете кучу объектов курса, студента и группы, они все связаны друг с другом через атрибуты отношений. Из-за этого невозможно выгрузить некоторые объекты из кэша и сохранить остальные. Сборщик мусора не может собирать только некоторые объекты из кэша, потому что все они указывают друг на друга с помощью циклических ссылок. Таким образом, кэш может быть удален только целиком, когда db_session закончен. Итак, если у вас есть одна давняя db_session, она не освободит память до конца. Но несколько меньшему db_session может потребоваться загрузить один и тот же объект из базы данных несколько раз. Таким образом, существует компромисс между памятью и производительностью

P.S. Даже если db_session завершена, соединение все равно будет удерживаться до завершения программы или явного вызова db.disconnect (). Pony неявно закрывает соединение, только если какое-то исключение из базы данных внутри db_session приводит к откату.

...