ASP - Представление о транзакциях
В коммерческих приложениях часто возникает необходимость выполнения сценариев и компонентов внутри транзакций. Транзакцией называют совокупность операций сервера, выполняемых в рамках единой операции, которая либо успешно выполняется в целом, либо не выполняется (например, создание заказов, проверка инвентарных запасов и выписка счетов). Если создать сценарий, который будет выполняться на сервере в рамках транзакции, ошибка в любой его части приведет к отмене всей транзакции.
Обработка транзакций ASP основана на среде транзакций службы компонентов, которая представляет собой систему обработки транзакций для разработки и развертывания высокопроизводительных, масштабируемых и надежных серверных приложений в рамках предприятия, в Интернете и в интрасетях организаций, а также для управления ими. Эта среда транзакций определяет модель программирования для создания распределенных компонентно-ориентированных приложений. Она является также средством для развертывания и управления этими приложениями.
Веб-сервер имеет встроенные функции, позволяющие создавать ориентированные на транзакции сценарии. При установке служб компонентов могут быть созданы пакеты компонентов, которые будут выполняться внутри транзакций.
О транзакциях
Транзакцией называют операцию, которая может быть выполнена успешно или завершиться с ошибкой только как единое целое. Надежное обновление баз данных может быть обеспечено только на основе обработки транзакций. При внесении большого числа взаимосвязанных изменений в базу данных или обновлении сразу нескольких баз данных необходима гарантия правильности всех операций по изменению данных. Ошибка на любом этапе изменения должна приводить к восстановлению первоначального состояния всех таблиц базы данных.
Самостоятельная реализация подобного механизма потребовала бы написания сценариев и компонентов, которые отслеживали бы нужные изменения и восстанавливали первоначальные данные при возникновении ошибок. Однако применение служб компонентов позволяет существенно упростить эту задачу. Достаточно просто объявить выполнение сценариев и компонентов в рамках транзакций. После этого их обработка будет координироваться автоматически службами компонентов. Понятие обработки транзакций применимо только к работе с базами данных. Службы компонентов не поддерживают восстановление исходного состояния после изменений в файловой системе или в других ресурсах, с которыми механизм транзакций не работает. Приложения могут работать только с базами данных, которые поддерживаются службами компонентов. На текущий момент имеется возможность работы с базами данных SQL Server, а также с другими базами данных, в которых реализована поддержка протокола транзакций XA (разработан консорциумом X/Open). В будущем службы компонентов смогут поддерживать и другие системы баз данных.
С помощью методов Server.Transfer и Server.Execute в операции может участвовать несколько страниц ASP. После вызова сценария, в котором присутствует директива @TRANSACTION со значением «Required», посредством метода Server.Transfer или Server.Execute, продолжается выполнение транзакции, запущенной вызванным файлом «.asp» (если последний уже участвовал в транзакции). Если файл «.asp» в транзакции еще не участвовал, при его вызове автоматически будет создана новая транзакция.
В следующем примере сценария показан запуск транзакции.
<%@ TRANSACTION=Required %> <% . . . 'End transaction. Server.Transfer("/BookSales/EndTrans.asp") %>
Однако в следующем сценарии происходит вызов другого сценария, также запускающего транзакцию.
<%@ TRANSACTION=Required%> <% 'Instantiate a custom component to close transactions. Set objSale = Server.CreateObject("SalesTransacted.Complete") . . . %>
В результате совместного действия обоих сценариев будет выполняться только одна транзакция. Дополнительные сведения о создании сценариев с командами Server.Transfer и Server.Execute можно найти в разделе Отправка содержимого в веб-обозреватель.
Объявление сценариев с поддержкой транзакций
Объявление страницы как поддерживающей транзакции приводит к тому, что все используемые в ней команды сценариев и объекты выполняются в контексте одной транзакции. Службы компонентов обрабатывают все данные, относящиеся к созданию и выполнению (успешному или неуспешному) транзакции. Чтобы объявить страницу как поддерживающую транзакции, в верхней части страницы необходимо поместить директиву @TRANSACTION.
<%@ TRANSACTION = значение %>
Дополнительные сведения об аргументе значение приводятся в справке по директиве @TRANSACTION.
Директива @TRANSACTION должна быть самой первой строкой на странице. Если это не так, возникает состояние ошибки. Эта директива также должна добавляться на каждую участвующую в транзакции страницу. Завершение текущей транзакции происходит одновременно с окончанием выполнения сценария.
В большинстве приложений контекст транзакции требуется только для определенных операций. Например, на веб-узле авиакомпании сценарии с поддержкой транзакций могут применяться для продажи билетов и бронирования мест. Безопасный запуск всех прочих сценариев может быть обеспечен и вне контекста транзакции. В с необходимостью применения транзакций только в отношении страниц, которые требуют обработки транзакций, объявление файла приложения Global.asa как поддерживающего транзакции невозможно.
Если транзакция завершается с ошибкой, службы компонентов восстанавливают состояние до начала всех изменений по всем ресурсам с поддержкой транзакций. В настоящее время полная поддержка транзакций обеспечивается только серверами баз данных, поскольку безопасной обработке именно этих данных придается особое значение при разработке приложений для организаций. Службы компонентов не поддерживают восстановления после изменений в файловой системе на жестком диске, переменных приложения и сеанса ASP или семейств. Однако, как будет показано дальше, не исключена возможность создания сценариев, которые будут использовать механизм транзакций для решения упомянутых задач. Так, можно разработать сценарий, в котором, транзакция будет успешно завершаться или прерываться в результате ошибки операции (например записи данных в файл).
Нормальное и принудительное завершение сценария
Наблюдая за выполнением транзакции, службы компонентов определяют результат ее выполнения — успешный или с ошибкой. В сценарии может быть в явном виде объявлено принудительное завершение транзакции посредством вызова процедуры ObjectContext.SetAbort. Например, подобное завершение операции возможно при получении ошибки компонента в результате нарушения правила обработки финансовых данных (например отрицательное сальдо счета) или при ошибке в операции, не относящейся к транзакции (например чтение или запись в файл). Транзакция также принудительно завершается, если время ожидания для страницы истекает до нормального завершения транзакции.
Запись событий транзакции
Результат выполнения транзакции не может быть определен самим сценарием. Эта задача решается с помощью событий, которые могут быть вызваны при нормальном или принудительном завершении транзакции. Рассмотрим пример сценария, в котором выполняется операция зачисления средств на банковский счет. Предположим, что в зависимости от состояния транзакции пользователю должны возвращаться разные веб-страницы. Это можно осуществить с помощью событий OnTransactionCommit и OnTransactionAbort.
<%@ TRANSACTION=Required %> <% 'Buffer output so that different pages can be displayed. Response.Buffer = True %> <HTML> <BODY> <H1>Welcome to the online banking service</H1> <% Set BankAction = Server.CreateObject("MyExample.BankComponent") BankAction.Deposit(Request("AcctNum")) %> <P>Thank you. Your transaction is being processed.</P> </BODY> </HTML> <% 'Display this page if the transaction succeeds. Sub OnTransactionCommit() %> <HTML> <BODY> Thank you. Your account has been credited. </BODY> </HTML> <% Response.Flush() End Sub %> <% 'Display this page if the transaction fails. Sub OnTransactionAbort() Response.Clear() %> <HTML> <BODY> We are unable to complete your transaction. </BODY> </HTML> <% Response.Flush() End Sub %>
Регистрация компонента в диспетчере служб компонентов (Component Services Manager)
Для участия в транзакции компонент должен быть зарегистрирован в приложении COM+ и настроен как требующий обработки транзакций. Так, в сценарии обработки заказов с вызовом соответствующих компонентов для обновления баз данных запасов и платежей оба эти компонента должны выполняться в контексте транзакции. В случае ошибки выполнения любого из них службы компонентов обеспечивают восстановление первоначального состояния базы данных и отмену всего заказа. Для отдельных компонентов, например Ad Rotator, транзакции не требуются.
Регистрация и настройка компонентов с поддержкой транзакций осуществляется с помощью диспетчера служб компонентов. Компоненты обязательно должны регистрироваться в приложении COM+. Однако не следует добавлять компоненты во внутреннее для IIS приложение COM+, с этой целью необходимо создать собственное приложение COM+. Как правило, все пользовательские компоненты размещаются в одном приложении Library. Компоненты приложений Library могут использоваться различными приложениями ASP и выполняться в запускаемых ими процессах.
Компоненты с поддержкой транзакций могут регистрироваться и в приложении Server — приложении COM+, которое всегда выполняется как самостоятельный процесс на сервере. Приложения Server для компонентов с поддержкой транзакций применяются для обеспечения безопасности на основе ролей или доступа к компонентам приложений, которые выполняются на удаленных компьютерах.
Работа с диспетчером служб компонентов требует установки служб компонентов.
Область действия объекта
В общем случае нет необходимости сохранять объекты, которые создаются из COM-компонента в объектах ASP Application или Session. Действие объектов COM автоматически заканчивается после завершения транзакции. Поскольку объекты Session и Application предназначены для экземпляров, которые могут использоваться несколькими страницами ASP, они не должны содержать объекты, освобождаемые по окончании транзакции.
Сценарий ASP является корнем, или началом, объявленной транзакции. Любой объект COM, используемый на странице ASP с поддержкой транзакций, считается частью транзакции. После завершения операции используемые на странице объекты COM отключаются; это относится и к тем из них, которые были сохранены в объекте Session или Application. Все последующие попытки вызова объекта, область действия которого ограничена сеансом или приложением, с другой поддерживающей транзакции страницы будут обречены на неудачу.
Поочередное выполнение транзакций
При обновлении базы данных на удаленном сервере может привести к задержке выполнения и даже принудительному завершению транзакции, связанным с задержками и ошибками в сети. Поскольку транзакция должна выполняться как единый процесс, работа приложения может быть приостановлена в ожидании сообщения удаленного сервера об ее успешном или принудительном завершении. Транзакция может также принудительно завершиться в связи с невозможностью отправки данных для обновления базы данных.
Для тех обновлений, которые должны быть выполнены одновременно, целесообразно отменить или задержать транзакцию до тех пор, пока не будет обеспечена возможность выполнения всех ее составляющих. Так, приложение для заказа билетов должно одновременно завершить операции списания со счета в банке заказчика и зачисления на счет в банке авиакомпании. Если обновление происходит в рамках транзакции, но может быть выполнено в последнюю очередь, заказчик может не дожидаться завершения этого процесса. В примере с заказом авиабилетов транзакция может отправлять также особый запрос на поставку продовольствия или обновлять сведения о дальности полета. Эти операции обязательно должны быть выполнены, но их срочность невысока.
Включить одно или несколько обновлений в отправляемое на удаленный сервер сообщение транзакции позволяют службы очереди сообщений. Их использование гарантирует доставку обновлений на удаленный сервер даже в тех случаях, когда сервер или сеть временно недоступны. После того как приложением будет получено сообщение об успешном завершении этой операции, выполнение транзакции может быть продолжено.