12 сентября 2009 г.

Для чего нужны транзакции

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

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

В 1С для работы с транзакциями имеются три специальных процедуры:

  • НачатьТранзакцию(<Режим блокировок>)
    Открывает транзакцию. Необязательный параметр <Режим блокировок> типа РежимУправленияБлокировкойДанных может иметь значения Автоматический и Управляемый. Значение по умолчанию - Автоматический.
  • ЗафиксироватьТранзакцию()
    Завершает успешную транзакцию. Все изменения, внесенные в информационную базу в процессе транзакции, будут записаны.
  • Отменить Транзакцию()
    Отменяет открытую ранее транзакцию. Все изменения, внесенные в информационную базу в процессе транзакции, будут отменены.

Процедуры управления транзакциями удобно использовать совместно с оператором обработки исключительных ситуаций Попытка.

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

Попытка
    НачатьТранзакцию();
    
    КонтрагентОбъект = Справочники.Контрагенты.СоздатьЭлемент();
    КонтрагентОбъект.Наименование = НаименованиеКонтрагента;
    //Записываем другие реквизиты контрагента
    КонтрагентОбъект.Записать();
    КонтрагентСсылка = КонтрагентОбъект.Ссылка;
    
    ДоговорОбъект = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
    ДоговорОбъект.Владелец = КонтрагентСсылка;
    ДоговорОбъект.Наименование = НаименованиеДоговора;
    //Записываем другие реквизиты договора
    ДоговорОбъект.Записать();
    
    РСОбъект = Справочники.БанковскиеСчета.СоздатьЭлемент();
    РСОбъект.Владелец = КонтрагентСсылка;
    РСОбъект.НомерСчета = НомерРасчетногоСчета;
    //Записываем другие реквизиты договора
    РСОбъект.Записать();
    
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;

Как это работает.

В случае успешного выполнения последовательности операторов попытки, оператор ЗафиксироватьТранзакцию() завершает транзакцию, записывая все изменения, внесенные в информационную базу. Далее управление передается оператору, следующему за ключевым словом КонецПопытки.

Если же в процессе выполнения операторов попытки происходит ошибка времени выполнения, то выполнение оператора, вызвавшего ошибку, прекращается и управление передается последовательности операторов исключения. Оператор ОтменитьТранзакцию() отменяет все изменения, внесенные в информационную базу в процессе транзакцию. Затем выдается сообщение об ошибке. Далее управление передается оператору, следующему за ключевым словом КонецПопытки.

Особо следует остановиться на транзакциях при проведении документов. С одной стороны, это типичный случай, когда необходимость транзакции очевидна. Но включать операторы управления транзакциями в процедуру обработки проведения документа нет необходимости, так как сама система включает их неявно. Так что любой документ по определению проводится в рамках транзакции.

Внутри транзакции крайне не рекомендуется использовать операторы, ожидающие отклик пользователя, такие как, например, Предупреждение(), Вопрос(), ВвестиЗначение() и т. п. И вообще время выполнения транзакций нужно стараться свести к минимуму. То же самое можно сказать и о проведении документов.

Надеюсь, что все понятно. Есть вопросы? Пишите, обсудим

Комментировать в ВКонтакте

Комментировать в Facebook

Комментировать в Blogger

Комментариев нет:

Отправить комментарий