Учет без рутины: как настроить автоматизацию в 1С
Ловушка первая: пакетное создание документов в одной транзакции
Самый распространённый паттерн автоматизации — обработка, которая за один цикл создаёт десятки или сотни документов. Код выглядит логично, но на практике приводит к долгим блокировкам таблиц, взаимоблокировкам (deadlock) и «зависанию» базы на время выполнения.
Как обычно пишут
Процедура СоздатьДокументыПоДанным(ТаблицаДанных)
Для Каждого Строка Из ТаблицаДанных Цикл
Док = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
Док.Дата = ТекущаяДата();
Док.Контрагент = Строка.Контрагент;
// ... заполнение реквизитов
Док.Записать(РежимЗаписиДокумента.Проведение);
КонецЦикла;
КонецПроцедуры
На первый взгляд — всё верно. Но если ТаблицаДанных содержит 500 строк, а каждый документ при проведении блокирует регистры и ссылки, то транзакция (неявно открытая для каждого Записать) может длиться минуты. В это время другие пользователи увидят ошибки «Запись заблокирована» или «Взаимоблокировка».
Правильный подход: разделение на транзакции и фоновые задания
Процедура СоздатьДокументыПоДанным(ТаблицаДанных)
ПараметрыЗадания = Новый Структура("ТаблицаДанных", ТаблицаДанных);
ФоновоеЗадание = ЗапуститьФоновоеЗадание("СоздатьДокументыВФоне", ПараметрыЗадания);
КонецПроцедуры
Процедура СоздатьДокументыВФоне(ТаблицаДанных, АдресХранилища) Экспорт
// Разбиваем на пакеты по 10-20 документов
РазмерПакета = 20;
Для Индекс = 0 По ТаблицаДанных.Количество() - 1 Цикл
Строка = ТаблицаДанных[Индекс];
Док = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
// ... заполнение
Док.Записать(РежимЗаписиДокумента.Проведение);
// Каждый документ - отдельная транзакция, блокировки короткие
Если Индекс % РазмерПакета = 0 И Индекс > 0 Тогда
// Пауза для снятия блокировок
ОбработкаПрерыванияВыполнения();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Ключевой тезис: автоматизация не должна превращать базу в монолитную трансакцию. Каждый документ — своя транзакция, каждый пакет — пауза для «проветривания» блокировок.
Ловушка вторая: регламентные задания — молчаливый убийца производительности
Регламентные задания — удобный инструмент для автоматизации. Но если не контролировать их перекрытие и длительность, они начинают «поедать» ресурсы сервера и блокировать друг друга.
Сценарий-катастрофа
- Задание «Обновление курсов валют» запускается каждые 5 минут, но соединение с внешним сервером иногда зависает на 10 минут.
- Задание «Закрытие месяца» стартует по расписанию, но накладывает блокировки на регистры, которые нужны утреннему заданию «Расчёт зарплаты».
- В результате — взаимоблокировки, регламентные задания накапливаются, и администратор видит в журнале регистрации только «Ошибка при выполнении регламентного задания».
Что делать
- Контролировать перекрытие — в начале задания проверять, не выполняется ли уже такое же задание. Использовать таблицу «Настройки выполнения заданий» или блокировку через
ОбщегоНазначения.БлокировкаРегламентногоЗадания(). - Устанавливать тайм-аут — для HTTP-запросов внутри заданий передавать параметр
Таймаутв конструкторHTTPСоединение. - Разделять по приоритетам — критичные задания (например, синхронизация с банком) запускать в отдельном сеансе через
ЗапуститьФоновоеЗадание, а не регламентную очередь.
// Пример проверки на перекрытие перед стартом
Процедура ВыполнитьАвтоматическоеСозданиеДокументов() Экспорт
Если ЗаданиеУжеВыполняется("АвтоматическоеСозданиеДокументов") Тогда
Возврат;
КонецЕсли;
// ... основная логика
КонецПроцедуры
Функция ЗаданиеУжеВыполняется(ИмяЗадания) Экспорт
// Используем НепосредственноеВыполнениеЗапроса через ИТС
Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 1 1 ИЗ РегламентныеЗадания ГДЕ Имя = &Имя И Состояние = &Выполняется");
Запрос.УстановитьПараметр("Имя", ИмяЗадания);
Запрос.УстановитьПараметр("Выполняется", "Выполняется");
Возврат Запрос.Выполнить().Пустой() = Ложь;
КонецФункции
Совет: никогда не запускайте регламентное задание без логирования длительности и ошибок. ИспользуйтеЗаписьЖурналаРегистрациис уровнемПримечаниедля отметки начала и окончания.
Ловушка третья: интеграция «в лоб» вместо выноса в сервис
Когда автоматизация требует регулярного обмена с внешними системами (обмен с сайтом, CRM, банком), многие разработчики выполняют все запросы прямо в контексте сеанса 1С. Это приводит к блокировкам на время ожидания ответа от внешнего сервера.
Сравнение подходов
Подход А (внутренний): обработка в цикле вызывает HTTPСоединение.Получить() для каждого документа. При зависании сервера — вся база блокируется.
Подход Б (фоновый сервис): внешняя программа (например, на Python или Node.js) через HTTP-сервисы 1С помещает данные в очередь. Регламентное задание разбирает очередь пакетами по 10-15 запросов, снимая блокировку после каждого документа.
// Пример тела HTTP-сервиса, который принимает данные для создания документа
Функция ПринятьЗаказИзВнешнейСистемы(Запрос) Экспорт
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Помещаем во временную таблицу или очередь
Очередь = РегистрыСведений.ОчередьЗаказов.СоздатьНаборЗаписей();
// ... заполнение
Очередь.Записать();
Возврат Новый HTTPОтвет(200);
КонецФункции
Такой подход позволяет основной базе не ждать внешнего сервера — данные накапливаются, а обработка происходит в фоне с контролируемыми блокировками.
Практическое руководство: чек-лист перед запуском автоматизации
- Проверка блокировок — если создаёте много документов, включите
УправлениеБлокировками.УстановитьРежимБлокировки(РежимУправленияБлокировками.Автоматический)и используйтеУправлениеБлокировками.ПопробоватьЗаблокировать()для критических таблиц. - Проверка дубликатов — перед созданием документа выполните поиск по уникальным реквизитам (например, номер документа из внешней системы). Используйте
НайтиПоРеквизиту. - Логирование — каждое действие автоматизации должно записываться в регистр или журнал с указанием времени, результата, ошибки. Иначе вы не сможете отладить сбой через месяц.
- Мониторинг фоновых заданий — регулярно проверяйте очередь фоновых заданий через стандартную обработку «Управление фоновыми заданиями». Удаляйте зависшие.
- Тестирование на копии — перед запуском автоматизации на рабочей ИБ обязательно прогоните на копии с полным объёмом данных. Особенно если используется пакетная вставка.
Типичные ошибки (и как их избежать)
| Ошибка | Последствие | Решение |
|---|---|---|
| Создание документа без проверки на существование | Дубликаты, нарушение уникальности нумерации | Использовать НайтиПоНомеру или НайтиПоРеквизиту |
| Необработанные исключения в фоновом задании | Задание завершается с ошибкой, данные не созданы | Обернуть логику в Попытка…Исключение и записать ошибку в журнал |
| Отсутствие паузы между пакетами документов | Долгие блокировки, «зависание» сеанса | Вставлять ОбработкаПрерыванияВыполнения() каждые N документов |
Использование Записать(РежимЗаписиДокумента.Проведение) для каждого документа в цикле | Долгие блокировки, риск взаимоблокировок | Разбивать на пакеты и использовать фоновые задания |
Попробовать НОПик →