Транзакции в 1С 8.3

Курс

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

Транзакция — это некий набор действий с базой данных, который может быть или полностью выполнен или полностью не выполнен. С точки зрения базы данных это неделимая операция. Если какое-то действие в транзакции не будет выполнено, то будут отменены все действия уже выполненные в этой транзакции (откат транзакции). Грубо говоря транзакция работает по принципу «или все или ничего».

Например, выполняется изменение цен товаров в регистре сведений. В регистре 1000 записей. Если без транзакции начать повышение всех цен на 10% и на 501 записи возникнет ошибка, то первые 500 записей уже будут изменены. Для второго запуска изменения цен, нужно как-то отбросить из выборки уже измененные записи, иначе для них повышение будет уже больше чем на 10%.

Если то же самое действие выполнять в транзакции, то при ошибке на 501 записи, первые 500 изменений будут отменены. Можно без проблем запускать изменение второй раз.

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

Свойства транзакции (требования ACID):

  • Атомарность (Atomicity) — будет выполнено или все, или ничего.
  • Согласованность (Consistency) — после выполнения система будет в согласованном состоянии. Пример несогласованного состояния, когда контрагента не записали, а договор с битой ссылкой на контрагента записали.
  • Изолированность (Isolation) — пока транзакция выполняется, другие транзакции не повлияют на ее результат. Например, одновременно две транзакции меняют одну запись с ценой в регистре. Первая изменила со 100 до 110. Вторая тоже со 100 но до 120. Вторая транзакция была записана позже, поэтому результат первой транзакции не сохранился. Данное свойство обеспечивает, что транзакции выполняются изолированно друг от друга. То есть пока не закончится первая транзакция, вторая не может изменить ту же запись в регистре.
  • Надежность или устойчивость (Durability) — сбой после успешной транзакции не должен отменять ее результат.

Явные и неявные транзакции

Транзакции в 1С могут быть явными и неявными. Неявные транзакции открывает сама платформа в следующих случаях:

  • При любом изменении данных (создание, удаление, обновление).
  • При чтении набора записей регистра методом Прочитать

Обработчики событий модуля объекта и модуля набора записей, которые связаны с записью всегда выполняются в транзакции. Это обработчики ПередЗаписью и ПриЗаписи, а также ОбработкаПроведения для документов.

Явное открытие транзакции выполняется с помощью метода НачатьТранзакцию. Чтобы закрыть транзакцию используется метод ЗафиксироватьТранзакцию. Все что будет расположено между данными методами будет выполнено в одной транзакции:

Если открыть транзакцию методом НачатьТранзакцию, но не закрыть методом ЗафиксироватьТранзакцию, то все изменения будут потеряны.

Чтобы отменить уже открытую транзакцию применяется метод ОтменитьТранзакцию:

Если попробовать вызвать методы ЗафиксироватьТранзакцию или ОтменитьТранзакцию, но при этом транзакция еще не была открыта, то будет выброшено исключение «Транзакция не активна»:

Транзакция не активна

Чтобы проверить открыта ли сейчас транзакция используется метод ТранзакцияАктивна. Он вернет Истина, если транзакция была открыта и Ложь в противном случае.

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

То же самое касается внешних объектов по отношению к 1С. Например, если в транзакции программно создать файл на диске, а потом отменить транзакцию, то файл сам не удалится.

Однако, если в транзакции был записан новый объект и транзакция была отменена, то у программного объекта будет очищено значение ссылки и код или номер. То же самое касается признака проведения документа, он будет возвращен к состоянию до начала транзакции:

Вложенные транзакции

Транзакции в 1С могут быть вложенными. При этом на уровне СУБД это не будет вложенной транзакцией. Это будет одна транзакция. Фиксация вложенной транзакции на уровне СУБД игнорируется. Если зафиксировать вложенную транзакцию, а потом отменить внешнюю — то все что было в обоих транзакциях будет отменено:

Если отменить вложенную транзакцию, то все что можно будет сделать с внешней транзакцией — это тоже отменить ее:

Если количество вызовов метода ЗафиксироватьТранзакцию будет меньше чем количество вызовов метода НачатьТранзакцию, то вся транзакция будет отменена.

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

Вложенные транзакции могут быть неявными. Например, при проведении документа выполняется запись движений в регистр. При записи движений будет открыта неявная вложенная транзакция.

Количество вложенных транзакций не ограничено.

Получается что транзакции в 1с могут быть вложенными, но при этом 1с не поддерживает вложенные транзакции (это все будет одна транзакция).

Обработка исключений в транзакции

Ошибки при работе с базой данных можно поделить на два вида:

  1. Восстановимые
  2. Невосстановимые

Невосстановимые приводят к завершению работы платформы. Если невосстановимая ошибка возникла в транзакции, то транзакция будет отменена.

Восстановимые ошибки не приводят к завершению работы платформы. Их можно обработать через конструкцию Попытка — Исключение. Однако если во вложенной транзакции возникла ошибка при записи в базу данных, которая была обработана конструкцией Попытка — Исключение, то теперь всю транзакцию можно только отменить:

Из-за этого можно столкнуться с такой ошибкой как «В данной транзакции уже происходили ошибки!»:

Так как при записи утюга в базу данных было выброшено исключение, то теперь транзакция не может быть завершена. Платформа предоставляет разработчику самому обработать данную ситуацию. Но теперь при первом обращении к базе данных, будет выброшено исключение «В данной транзакции уже происходили ошибки!»:

В данной транзакции уже происходили ошибки!

Из-за этого часто бывает сложно найти причину ошибки. Потому что в сообщении об ошибке будет указана строка «Пока ВсеДоки.Следующий() Цикл», хотя фактически ошибка возникла на строке «Утюг.Записать();». Чтобы избежать таких непонятных ошибок, нужно в блоке Исключение писать ВызватьИсключение чтобы исключение было передано выше по стеку вызовов:

В этом случае будет понятное сообщение об ошибке:

Исключение в транзакции

В целом обработка исключений в транзакции должна выглядеть примерно так:

И ни в коем случае не так:

В этом случае мы рискуем получить труднодиагностируемое сообщение об ошибке.


Подписывайтесь на группу ВКонтакте , где я публикую ссылки на новые статьи с данного сайта, а также интересные материалы с других ресурсов по программированию в 1С
Понравилась статья? Поделиться с друзьями:
Комментарии: 1
  1. Алексей

    Отличный материал, примеры понятные.

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Используя этот сайт, Вы даете согласие на использование cookies. На данном этапе Вы можете отказаться от использования cookies, настроив необходимые параметры в своем браузере.
ok