Как устранить ошибку расчета итогов после ТА и блокировки при проведении документов в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В многопользовательской среде 1С:Предприятия 7.7 разработчики и администраторы нередко сталкиваются с ситуацией, когда при одновременной работе пользователей проведение документов аварийно прерывается сообщениями «Невозможно рассчитать итоги после ТА» или длительными блокировками системной таблицы 1SSYSTEM. На первый взгляд кажется, что платформа разделяет проведение документа и сдвиг точки актуальности (ТА) на две разные операции, между которыми возникает временной зазор. Разберем механику работы платформы, выясним истинные причины коллизий и рассмотрим проверенные способы их устранения.

Архитектура проведения и точка актуальности в 1С 7.7

Проанализируем базовый принцип: в платформе 1С 7.7 проведение документа в реальном времени и перемещение точки актуальности неделимы и всегда выполняются внутри одной транзакции. Никакого промежуточного состояния, когда документ уже провелся, а ТА еще не сдвинулась, на уровне ядра базы данных физически не существует. При проведении документа на ТА платформа блокирует монопольно единственную запись в таблице 1SSYSTEM, записывает движения регистров, обновляет реквизиты ТА (дату, время и внутренний ID документа) и фиксирует транзакцию.

Почему же возникает ошибка невозможности расчета итогов? Механизм ВременныйРасчет() в регистрах оперативного учета умеет рассчитывать остатки только на позиции, которые находятся строго до или на момент ТА. Если платформа пытается рассчитать временные итоги на точку, расположенную в будущем относительно текущей ТА, транзакция немедленно падает с системным отказом.

Основные причины рассинхронизации и появления документов в будущем

Выясним, откуда берутся документы, опережающие точку актуальности, из-за которых блокируется нормальная работа пользователей:

  1. Рассинхронизация системного времени на компьютерах. Если на рабочих станциях пользователей, терминальных серверах или удаленных точках время расходится даже на 10–30 секунд, документ, проведенный с опережающей машины, сдвигает ТА вперед. При попытке провести документ с отстающего компьютера система воспринимает его проведение как заднее число либо сталкивается с конфликтом позиционирования.
  2. Документы с автопозиционированием в конец суток. Если в конфигурации используются методы автоматической установки времени на конец дня (например, 23:59:59 для документов инвентаризации, списания или перемещения), ТА моментально перемещается в конец текущей даты. После этого любые оперативные документы, создаваемые в течение дня, попадают в прошлое относительно ТА.
  3. Фоновые обмены пакетами УРБД. При загрузке данных распределенной информационной базы приходят документы из периферийных узлов. Если в удаленной базе системные часы спешили или оператор ввел накладную будущей датой, загрузка пакета перемещает ТА в центральной базе вперед, одновременно вызывая длительную блокировку таблицы 1SSYSTEM.
  4. Ошибки в модуле документа при проверке актуальности итогов. Некорректный код инициализации расчета регистров часто запускает временный расчет в неподходящих ситуациях.

Корректировка программного кода в модуле документа

Рассмотрим типовую ошибку в процедуре ОбработкаПроведения(). Часто разработчики пишут условие для получения временных остатков только через метод ИтогиАктуальны():


Если ИтогиАктуальны() = 0 Тогда
    Регистры.ВременныйРасчет(1);
    РассчитатьРегистрыНа(ТекущийДокумент());
КонецЕсли;

Посмотрим на проблему такого подхода: если документ по какой-то причине проводится позже ТА, функция ИтогиАктуальны() вернет значение 0. Программа зайдет в условие и попытается выполнить метод РассчитатьРегистрыНа() на момент позже ТА, что вызовет фатальное падение. Чтобы этого избежать, добавим дополнительную проверку через встроенную функцию СравнитьТА():


// СравнитьТА() возвращает:
// -1 : документ раньше ТА
//  0 : документ на ТА
//  1 : документ позже ТА

Если (ИтогиАктуальны() = 0) И (СравнитьТА() = -1) Тогда
    Регистры.ВременныйРасчет(1);
    РассчитатьРегистрыНа(ТекущийДокумент());
КонецЕсли;

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

Настройка параметров проведения в интерфейсе и программное управление

Разберем параметры позиционирования оперативных документов в конфигурации:

  1. Интерактивная настройка: в меню Сервис — Параметры — закладка «Оперативный учет» проверяем флаг «При проведении после ТА заменять время на текущее» (или переносить ТА на документ). Это гарантирует, что новые документы автоматически подтягиваются к актуальному потоку времени.
  2. Программное управление через модуль формы: для документов, где важно исключить вопросы пользователю и жестко зафиксировать оперативное поведение, используем метод ПроводитьПослеТА(). Разберем синтаксис:

// В модуле формы документа, например, в процедуре ПриОткрытии():
// 1 - проводить документ в реальном потоке времени (время ставится после ТА)
ПроводитьПослеТА(1, 1);

Почему перенос ТА далеко вперед на месяц — опасная практика?

Иногда администраторы пытаются решить проблему установкой точки актуальности вручную на конец месяца или на первое число следующего месяца. Разберем последствия этого шага:

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

Комплексный регламент устранения проблемы

Для надежной работы системы при параллельной нагрузке применим следующие шаги:

  1. Настроим службу NTP: включим принудительную синхронизацию времени по единому серверу точного времени на всех терминалах, сервере СУБД и удаленных узлах с периодичностью синхронизации не реже одного раза в час.
  2. Оптимизируем регламент обмена УРБД: исключим тяжелые дневные пакеты обмена, идущие часами. Перейдем на частые короткие обмены (каждые 10–15 минут) с разбивкой данных по небольшим транзакциям, либо перенесем тяжелые синхронизации на нерабочее время.
  3. Исключим ввод документов «будущим временем»: настроим в модулях проверку даты и времени, запрещающую операторам вручную указывать будущую дату или смещать время документов вперед.
  4. Внедрим внешнюю компоненту 1С++: при пиковых нагрузках заменим тяжелые выборки остатков штатными регистрами на прямые SQL-запросы к таблицам остатков с хинтом NOLOCK через класс ODBCRecordset. Это позволит считывать актуальные остатки без наложения блокировок и без механизма временного расчета.
← На главную