Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Shablony_korporativnykh_prilozheniy_Fauler_M.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
3.82 Mб
Скачать

Сохранение состояния сеанса в базе данных (Database Session State)

Сохраняет состояние сеанса как обычное содержимое базы данных

Принцип действия

Когда клиент направляет серверу запрос, первое, что делает серверный объект, — об­ращается к базе данных и извлекает из нее данные, необходимые для удовлетворения за­проса. Затем он выполняет всю необходимую работу и записывает обновленные данные обратно в базу данных.

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

Данные, используемые в ходе выполнения запроса, как правило, представляют собой комбинацию промежуточных данных сеанса, имеющих смысл только в контексте теку­щего взаимодействия с базой данных, и постоянных данных, имеющих смысл во всех взаимодействиях.

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

Итак, как же отделить данные сеанса от основного содержимого базы данных? Пожа­луй, самое очевидное решение — добавить к каждой строке базы данных, которая может содержать промежуточные данные сеанса, специальное поле. В качестве последнего можно использовать логическое поле с именем наподобие isPending. Однако гораздо лучше применить поле, содержащее идентификатор сеанса, что позволит легко отобрать все данные, принадлежащие конкретному сеансу. В этом случае всем запросам, извле­кающим постоянные данные, понадобится отбросить промежуточные данные с помо­щью таких выражений, как sessioniD is not null, или воспользоваться необходи­мыми фильтрами.

Применять поле с идентификатором сеанса довольно неудобно, потому что всем при­ложениям, имеющим дело с записями базы данных, понадобится знать о присутствии этого поля, чтобы по ошибке не извлечь промежуточные данные сеанса. Иногда это не­удобство можно устранить с помощью представлений и фильтров, однако применение представлений связано со своими расходами.

Возможной альтернативой является создание отдельного набора таблиц с промежу­точными данными. Таким образом, если в базе данных есть таблицы для хранения зака­зов и пунктов заказов, понадобится добавить еще две таблицы для хранения промежу­точных состояний заказов и промежуточных состояний пунктов заказов. Промежуточные данные будут сохраняться в промежуточных таблицах, а их окончательные варианты — в обычных, "настоящих" таблицах. Это позволит избежать многих неудобств, связанных с разделением данных, однако потребует реализации в слое отображения дополнитель­ной логики выбора тех или иных таблиц, что, несомненно, усложнит структуру системы.

Зачастую постоянные данные таблиц подчиняются определенным правилам целост­ности, которые не распространяются на промежуточные данные. В этом случае вы може­те отключить правила целостности в применении к промежуточным таблицам и активи­зировать их, если они все-таки понадобятся. К промежуточным данным не применяется и проверка на логическую правильность. Разумеется, на определенных этапах сеанса мо­жет понадобиться провести ту или иную проверку на правильность, однако это обычно определяется в логике серверного объекта.

Промежуточные таблицы должны представлять собой точные копии настоящих таб­лиц. В этом случае логика отображения будет самой простой. Используйте в промежу­точных таблицах те же имена полей, что и в настоящих таблицах, а затем снабдите их до­полнительным полем с идентификаторами сеанса, чтобы легко отбирать данные, при­надлежащие определенному сеансу.

При сохранении промежуточных данных необходимо реализовать механизм, который будет удалять записи о брошенных или прерванных сеансах. Используя идентификатор сеанса, вы можете найти и уничтожить все ненужные данные. Если же пользователь мо­жет покинуть сеанс без уведомления сервера, понадобится организовать некоторую об­работку времени ожидания. Для этого можно воспользоваться демоном, который будет запускаться каждые несколько минут и выполнять проверку наличия устаревших дан­ных. Подобная схема обработки требует наличия в базе данных специальной таблицы, которая будет фиксировать время последнего взаимодействия с указанным сеансом.

Реализовать откат обновлений гораздо сложнее. Как выполнить откат сеанса, если в течение этого сеанса была обновлена существующая запись о заказе? Одно из воз­можных решений — не допускать отмену подобных сеансов. Все обновления сущест­вующих данных должны фиксироваться в таблице только в конце выполнения запроса. Эта схема очень проста и вполне соответствует видению процесса обновления самими пользователями. Все остальные альтернативы менее удобны, независимо от того, что вы используете — промежуточные поля или промежуточные таблицы. Для реализации описанной схемы при наличии промежуточных таблиц все обновляемые данные можно скопировать в промежуточные таблицы, выполнить в них необходимые изменения и пе­ренести данные обратно в таблицы с постоянными записями по окончании текущего се­анса. При использовании промежуточных полей подобные действия возможны только тогда, когда идентификатор сеанса является частью ключа записи. В этом случае в одной и той же таблице могут одновременно находиться значения старого и нового идентифи­каторов, что способно крайне затруднить работу с таблицей.

Если промежуточные таблицы будут считываться только объектами, обрабатываю­щими сеанс, необходимость представления состояния сеанса в табличном формате край­не мала. В этом случае имеет смысл воспользоваться крупным сериализованным объектом (Serialized LOB), в результате чего сохранение состояния сеанса в базе данных пре­вращается в сохранение состояния сеанса на стороне сервера (Server Session State).

При желании вы можете избежать всех этих трудностей, просто отказавшись от ис­пользования промежуточных данных. Другими словами, приложение можно спроекти­ровать таким образом, чтобы все его данные рассматривались как постоянные. Разумеется, это далеко не всегда возможно и зачастую способно привести систему в состояние пол­ной неразберихи (а потому наталкивает на мысль о необходимости явной обработки промежуточных данных). Тем не менее, если подобная возможность у вас есть, она зна­чительно облегчит реализацию сохранения состояния сеанса в базе данных.

Назначение

Сохранение состояния сеанса в базе данных является одним из возможных вариантов обработки состояний сеанса наряду с типовыми решениями сохранение состояния сеанса на стороне сервера и сохранение состояния сеанса на стороне клиента. Каждое из них имеет свои преимущества и недостатки.

Одним из наиболее спорных аспектов сохранения состояния сеанса в базе данных яв­ляется производительность. Использование серверных объектов без состояния разрешает применение пула объектов и облегчает выполнение кластеризации, что, разумеется, ока­зывает благоприятное влияние на производительность приложения. С другой стороны, необходимость извлечения и записи данных при выполнении каждого запроса влечет за собой определенные временные затраты. Для снижения этих затрат извлекаемые данные можно кэшировать, однако расходы на запись сократить нельзя.

Не менее важным аспектом является трудоемкость работ. Большая часть усилий про­граммистов затрачивается на обработку состояний сеанса. Таким образом, если у вас нет состояний сеанса и промежуточные данные допускается сохранять наряду с постоянны­ми, предпочтение следует отдать именно сохранению состояния сеанса в базе данных, по­скольку оно не требует дополнительных затрат на кодирование и не приводит к падению производительности приложения (если извлекаемые объекты кэшируются).

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]