Почему в типовых конфигурациях 1С не используется механизм «Записывать модифицированные» при проведении документов?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки конфигураций на платформе 1С:Предприятие 8 программисты часто сталкиваются с выбором: довериться автоматическим механизмам платформы или управлять процессами вручную. Одним из таких камней преткновения является свойство Записывать модифицированные в объекте Движения документа. На первый взгляд, автоматика кажется удобной, однако в типовых решениях (ERP, УТ, КА, БП) вендор последовательно отказывается от этого механизма в пользу явного управления записью. В этой статье мы подробно разберем, какие технические и архитектурные причины стоят за этим решением.

В чем суть механизма «Записывать модифицированные»?

Механизм Записывать модифицированные (или программный аналог WriteModified) предназначен для того, чтобы платформа самостоятельно определяла, какие наборы записей регистров были изменены в ходе процедуры ОбработкаПроведения, и записывала их в базу данных в самом конце транзакции. Казалось бы, это идеальный вариант: разработчику не нужно заботиться о вызове метода Записать() для каждого регистра. Но давайте проанализируем, почему этот подход не применим в высоконагруженных системах.

Проблема 1: Непрозрачность и сложность отладки

Рассмотрим ситуацию, когда запись движений происходит автоматически в конце транзакции. Если в процессе записи возникнет ошибка (например, нарушение уникальности записей или ошибка в подписке на событие), разработчику крайне сложно локализовать момент сбоя. Когда мы используем явный вызов Движения.ИмяРегистра.Записать(), мы точно видим в отладчике, на какой строке кода происходит обращение к СУБД. Это делает код детерминированным и предсказуемым. Автоматическая запись превращает финал процедуры проведения в «черный ящик», где ошибки могут всплывать в самый неожиданный момент, затрудняя диагностику.

Проблема 2: Особенности определения модифицированности

Выясним, как платформа на самом деле понимает, что набор записей «модифицирован». Платформа не сравнивает текущее состояние коллекции в памяти с данными в таблице базы данных (это было бы слишком ресурсоемко). Флаг Модифицированность устанавливается в значение Истина, как только к коллекции применяется любое действие, изменяющее ее состав: добавление записи, удаление или изменение свойств существующих элементов.

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

Проблема 3: Управление блокировками и предотвращение Deadlocks

В высоконагруженных системах критически важен порядок захвата ресурсов. При использовании автоматической записи платформа записывает все измененные регистры «пачкой» в конце транзакции. Порядок этой записи может быть неочевидным. Если один документ записывает сначала РегистрНакопления.Запасы, а затем РегистрНакопления.Продажи, а другой документ (или фоновое задание) делает это в обратном порядке, возникает риск взаимоблокировки (Deadlock).

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


// Сначала записываем те регистры, по которым проверяются остатки
Движения.ТоварыНаСкладах.Записать();

// Проверяем остатки, если ошибка - отказ
Если Не ПроверитьОстатки() Тогда
    Отказ = Истина;
    Возврат;
КонецЕсли;

// И только потом записываем остальные, менее критичные регистры
Движения.Продажи.Записать();

Проблема 4: Стратегия «Минимальной записи»

В современных типовых конфигурациях активно используется режим Удаление движений: Не удалять автоматически. Это позволяет реализовать стратегию минимальной записи. Суть ее заключается в том, что при перепроведении документа мы сначала считываем старые движения, сравниваем их с новыми и записываем набор в базу только в том случае, если обнаружены значимые отличия. Механизм Записывать модифицированные слишком груб для такой тонкой настройки — он просто видит факт обращения к коллекции и инициирует запись.

Проблема 5: Гибкость управления через ДополнительныеСвойства

Разберем, как вендор обходит ограничения платформы в БСП (Библиотеке стандартных подсистем). Вместо того чтобы полагаться на флаги модифицированности, используется структура ДополнительныеСвойства. В нее передаются инструкции о том, какие регистры нужно записывать в текущем контексте (например, при отложенном проведении или при обмене данными). Это позволяет коду «принимать решение» о записи, основываясь на бизнес-логике, а не на техническом факте изменения коллекции в памяти.

Выводы и рекомендации

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

  1. Непредсказуемость: сложно контролировать момент и порядок фиксации данных в БД.
  2. Избыточность: риск лишних операций записи при отсутствии фактических изменений в данных.
  3. Риск блокировок: отсутствие гибкого контроля над захватом таблиц СУБД.

Поэтому в реальных проектах мы рекомендуем придерживаться следующих правил:

  1. Устанавливать свойство Удаление движений в значение Не удалять автоматически.
  2. Использовать явный вызов Движения.ИмяРегистра.Записать() в конце процедуры проведения.
  3. Реализовывать алгоритмы проверки на «пустоту» и «измененность» перед записью, чтобы избежать лишних транзакций к базе данных.

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

← На главную