Одной из наиболее неприятных ситуаций для разработчика 1С является «плавающая» ошибка, когда программный код, работающий идеально в файловой базе, перестает корректно функционировать в серверном варианте (SQL). Рассмотрим, почему механизм проверки остатков может вести себя по-разному в зависимости от архитектуры базы данных и как нам подойти к решению этой задачи.
Прежде всего, важно осознать, что файловый вариант 1С:Предприятие и клиент-серверный вариант на базе MS SQL или PostgreSQL — это принципиально разные среды исполнения запросов. В файловой базе данные физически считываются из файла, а блокировки накладываются на уровне файловой системы. В серверном режиме запрос выполняет СУБД, применяя сложные механизмы оптимизации и уровни изоляции транзакций.
Рассмотрим основные факторы, влияющие на различие результатов:
SQL и в документации 1С четко указано: если в запросе не задана явная инструкция УПОРЯДОЧИТЬ ПО, сервер СУБД возвращает записи в том порядке, который кажется ему наиболее эффективным (например, по кластерному индексу). Это может приводить к тому, что при расчете остатков «в минус» мы получаем не тот набор данных, на который рассчитывали.Сервер 1С:Предприятия может использовать время операционной системы сервера, которое иногда отличается от времени локального компьютера, на котором вы запускаете файловую копию. Если ваша проверка остатков использует метод МоментВремени() или жестко заданные даты, это может приводить к захвату «лишних» или «недостающих» движений документа.Read Committed). Это означает, что при выполнении транзакции проведения, запрос к остаткам может не видеть тех движений, которые текущий документ уже успел записать, но еще не зафиксировал (или наоборот). Файловая база в силу своей архитектуры работает более прямолинейно, что создает иллюзию стабильности кода, который на самом деле содержит логические ошибки.Чтобы устранить разницу в поведении, давайте проанализируем наш код и применим следующие методы отладки:
1. Обеспечение детерминированности запроса
Никогда не полагайтесь на порядок записей, который возвращает платформа без явного указания УПОРЯДОЧИТЬ ПО. Если вы проверяете остатки по регистрам, убедитесь, что ваш запрос возвращает данные в строго определенной последовательности.
2. Проверка работы с датами
Посмотрим, как мы получаем период в коде. Рекомендуем использовать Граница с видом Включая на момент времени документа:
// Пример правильного формирования периода для проверки остатков
МоментВремениДокумента = ДокументОбъект.МоментВремени();
ГраницаОстатков = Новый Граница(МоментВремениДокумента, ВидГраницы.Включая);
Запрос.УстановитьПараметр("Период", ГраницаОстатков);
Использование объекта Граница позволяет платформе корректно обработать ситуацию «на момент времени» вне зависимости от типа СУБД.
3. Анализ итогов регистров
В серверных версиях 1С активно использует таблицу итогов. Если она повреждена, результаты запросов к остаткам будут непредсказуемыми. Попробуйте выполнить следующие действия:
Тестирование и исправление информационной базы, выбрав пункт Пересчет итогов.MS SQL Management Studio можно запустить обновление статистики для таблиц итогов регистра, чтобы оптимизатор запросов работал корректно.Если проблема сохраняется, мы рекомендуем выполнить следующие действия для локализации ошибки:
ПолучитьОстатки() виртуальной таблицы, предварительно убедившись, что все необходимые параметры заданы максимально точно.БлокировкаДанных перед чтением, чтобы гарантировать, что никто не изменяет остатки в момент вашей проверки.Помните, что серверная база — это высоконагруженная среда, где «неявные предположения» разработчика о том, как должны выбираться данные, почти всегда приводят к ошибкам. Будьте точны в описании периодов, сортировок и используйте стандартные механизмы блокировок 1С, тогда поведение программы станет предсказуемым и стабильным в любом режиме.