При выполнении регламентной операции «Закрытие месяца» (или расчете себестоимости запасов) в конфигурациях 1С (таких как «Управление нашей фирмой», «ERP Управление предприятием» или «Комплексная автоматизация») пользователи и разработчики часто сталкиваются с аппаратными и логическими сбоями. Один из самых неочевидных сбоев — это ошибка СУБД, сообщающая о повторном создании уже существующей временной таблицы.
В этой статье мы подробно разберем, почему возникает ошибка Временная таблица уже существует "ВременнаяТаблицаРешений", проанализируем математический алгоритм, который приводит к этой проблеме, и рассмотрим пошаговые методы её локализации и устранения в базе данных.
Для того чтобы понять природу этой ошибки, нам необходимо заглянуть внутрь программного кода проведения документа ЗакрытиеМесяца. В модуле объекта этого документа (или в общих модулях расчета себестоимости) выполняется расчет фактической стоимости списания запасов. Этот расчет производится итерационным методом путем решения системы линейных уравнений (СЛУ) в специальном цикле.
Давайте проанализируем текст запроса, который выполняется на каждой итерации этого цикла:
ВЫБРАТЬ
УзлыКорректировкиСтоимостиСписания.НомерУзла КАК НомерУзла,
СУММА(ВЫРАЗИТЬ(ВЫБОР
КОГДА УзлыКорректировкиСтоимостиСписания.Количество <> 0
ТОГДА ТаблицаРешений.Сумма * ВЫБОР
КОГДА УчетЗатрат.Количество = 0
ТАКЖЕ УчетЗатрат.Сумма
ИНАЧЕ УчетЗатрат.Количество
КОНЕЦ / УзлыКорректировкиСтоимостиСписания.Количество
ИНАЧЕ 0
КОНЕЦ КАК ЧИСЛО(23, 10))) КАК Сумма
ПОМЕСТИТЬ ВременнаяТаблицаРешений
ИЗ
РегистрСведений.УзлыКорректировкиСтоимостиСписания КАК УзлыКорректировкиСтоимостиСписания
ЛЕВОЕ СОЕДИНЕНИЕ УчетЗатрат КАК УчетЗатрат
ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаРешений КАК ТаблицаРешений
ПО УчетЗатрат.НомерУзла = ТаблицаРешений.НомерУзла
ПО УзлыКорректировкиСтоимостиСписания.Организация = УчетЗатрат.Организация
И УзлыКорректировкиСтоимостиСписания.СтруктурнаяЕдиница = УчетЗатрат.СтруктурнаяЕдиница
И УзлыКорректировкиСтоимостиСписания.СчетУчета = УчетЗатрат.СчетУчета
И УзлыКорректировкиСтоимостиСписания.Номенклатура = УчетЗатрат.Номенклатура
И УзлыКорректировкиСтоимостиСписания.Характеристика = УчетЗатрат.Характеристика
И УзлыКорректировкиСтоимостиСписания.Партия = УчетЗатрат.Партия
И УзлыКорректировкиСтоимостиСписания.ЗаказПокупателя = УчетЗатрат.ЗаказПокупателя
ГДЕ
УзлыКорректировкиСтоимостиСписания.Регистратор = &Регистратор
СГРУППИРОВАТЬ ПО
УзлыКорректировкиСтоимостиСписания.НомерУзла
ИНДЕКСИРОВАТЬ ПО
НомерУзла
;
В нормальном режиме работы СЛУ рассчитывает точные суммы списания за несколько итераций. Погрешность (отклонение) с каждым шагом цикла стремится к нулю. Когда точность расчетов достигает заданного порога, цикл завершается, временная таблица ВременнаяТаблицаРешений явно уничтожается в конце итерации с помощью команды УНИЧТОЖИТЬ, а полученные данные записываются в регистры.
Однако если в базе данных присутствуют отрицательные остатки (количественные или суммовые), математический алгоритм сходимости матрицы нарушается:
Сумма достигают гигантских размеров (сотни триллионов).ВЫРАЗИТЬ(... КАК ЧИСЛО(23, 10)) происходит критическая ошибка базы данных — «Арифметическое переполнение при преобразовании numeric к типу данных numeric».МенеджерВременныхТаблиц остается «живым» в контексте транзакции проведения документа.ПОМЕСТИТЬ ВременнаяТаблицаРешений. Платформа видит, что такая таблица уже зарегистрирована в менеджере, и выдает ошибку: Временная таблица уже существует "ВременнаяТаблицаРешений".Таким образом, дублирование временной таблицы — это лишь вторичный симптом, следствие аварийного прерывания транзакции. Истинная причина проблемы — математическая расходимость алгоритма из-за некорректных данных в регистрах.
Рассмотрим подробнее, как быстро найти и локализовать эту ошибку в информационной базе.
Первое, что мы должны сделать — проверить наличие классических «минусов» по запасам на складах на конец закрываемого месяца. Для этого воспользуемся стандартными отчетами конфигурации.
Если такие позиции найдены, необходимо устранить отрицательные остатки. Это можно сделать путем корректировки последовательности проведения документов, исправления цепочки документов поступления и реализации, либо с помощью документа «Инвентаризация запасов» (ввод излишков/списание недостач).
Бывают ситуации, когда количественный остаток по товару равен нулю или положителен, но при этом на складе «завис» отрицательный суммовой остаток. Такое происходит из-за ручных корректировок проводок, некорректного распределения дополнительных расходов или проведения документов «задним числом».
Для выявления таких аномалий проанализируем стоимостную оценку запасов:
0, а сумма отлична от нуля (особенно если она отрицательная).Любой стоимостной минус без количества нарушает логику расчета распределения затрат и приводит к делению на сверхмалые величины, вызывая расходимость алгоритма СЛУ.
Если база данных имеет внушительный объем, ручной поиск по отчетам может затянуться. В этом случае мы можем использовать конфигуратор и режим отладки для мгновенного определения виновника сбоя.
Рассмотрим по шагам, как локализовать проблемную номенклатуру:
ЗакрытиеМесяца (или соответствующий общий модуль расчета себестоимости).РешитьСЛУ или содержит итерационный цикл расчета стоимости списания).Запрос.ВыполнитьПакет().ТекущееОтклонение или МаксимальноеОтклонение).10.5 перескакивает на 150 000, затем на 18 000 000 000 и так далее), значит, мы нашли проблемную итерацию.
Запрос.МенеджерВременныхТаблиц.Таблицы.Найти("ТаблицаРешений").ПолучитьДанные().Выгрузить()
Сумма по убыванию. Мы сразу увидим строки с гигантскими нереалистичными суммами (например, -4.5168234E+18).НомерУзла для этой строки. Это идентификатор связи.УчетЗатрат (или регистра сведений УзлыКорректировкиСтоимостиСписания) по найденному номеру узла. В этой таблице будут четко указаны: Номенклатура, Характеристика, Склад и Партия, из-за которых расчет заходит в бесконечный цикл.После того как конкретная номенклатурная позиция определена, вам останется лишь открыть ее карточку движения (отчет «Карточка движения товара») и устранить первопричину — некорректный документ, породивший отрицательный остаток.
В некоторых случаях, когда необходимо заставить систему завершить расчет до конца, чтобы получить лог ошибок или локализовать расхождения программными средствами, разработчики временно увеличивают разрядность чисел в запросе.
Мы можем временно изменить конструкцию приведения типа в конфигураторе:
Вместо:
КОНЕЦ КАК ЧИСЛО(23, 10))) КАК Сумма
Пропишем:
КОНЕЦ КАК ЧИСЛО(38, 10))) КАК Сумма
Важное предупреждение: этот способ не решает проблему расхождения СЛУ! Он лишь предотвращает падение СУБД по ошибке переполнения разрядной сетки numeric. Это позволит алгоритму отработать все положенные итерации (обычно лимит составляет 50 или 100 итераций), после чего система аварийно завершит цикл по превышению лимита шагов и выдаст понятное текстовое сообщение в журнал регистрации с указанием конкретных проблемных узлов.
Подводя итоги, отметим, что ошибка Временная таблица уже существует "ВременнаяТаблицаРешений" при закрытии месяца — это классический маркер нарушения логической целостности учета запасов. Чтобы избежать подобных проблем в будущем, рекомендуем придерживаться следующих правил:
Используя предложенные нами методики анализа временных таблиц через отладчик, вы сможете локализовать и устранять подобные ошибки расчета себестоимости за считанные минуты.