В процессе эксплуатации клиент-серверных версий «1С:Предприятие» системные администраторы и разработчики часто сталкиваются с непредвиденными сбоями при проведении документов или формировании отчетов. Одним из наиболее резонансных и критических сбоев своего времени стала проблема релиза платформы 8.3.12.1412. В данной статье мы подробно проанализируем эту ситуацию, выясним технические причины сбоя СУБД и разберем по шагам, как полностью устранить эту проблему или временно обойти её, если быстрое обновление невозможно.
В процессе работы пользователи могут столкнуться с внезапным прекращением транзакций. Типичный сценарий: при попытке провести документ (например, в конфигурациях «Зарплата и Управление Персоналом», «ERP Управление предприятием» или «Бухгалтерия предприятия») система аварийно завершает операцию и выводит на экран критическое предупреждение:
«Ошибка СУБД: Microsoft SQL Server Native Client 11.0: The size (39) given to the type 'numeric' exceeds the maximum allowed (38)»
Иногда эта же ошибка в русскоязычном интерфейсе отображается как: «Размер (39), выделенный типу "numeric", превышает максимально допустимое значение (38)». Примечательно, что попытки обойти проблему простым перезапуском службы сервера «1С:Предприятия» или очисткой локального кэша не приносят долгосрочного результата. Ошибка может временно «исчезнуть» (например, после выгрузки-загрузки базы данных в файловый вариант и обратно на сервер), но при первой же массовой записи или проведении документов она возвращается снова.
Давайте разберем по шагам, что именно происходит на физическом уровне баз данных. Платформа 1С при выполнении запросов транслирует внутренний язык запросов в декларативный SQL-код, понятный СУБД Microsoft SQL Server.
В релизе платформы 8.3.12.1412 был допущен критический баг в механизме оптимизатора запросов. Сбой происходит тогда, когда в запросе одновременно выполняются два условия:
СУММА (SUM) для расчета числовых показателей.ИТОГИ (TOTALS) по группировкам.При трансляции такого запроса платформа динамически формирует временные таблицы на стороне MS SQL Server. В процессе расчета итогов по суммируемым полям алгоритм платформы некорректно вычисляет потенциальную разрядность результирующего поля и пытается назначить ему тип данных numeric(39). Однако архитектура Microsoft SQL Server (начиная со старых версий и заканчивая современными релизами) аппаратно и программно поддерживает максимальную точность типа данных numeric и decimal только до 38 знаков. Как только СУБД получает инструкцию создать колонку или параметр с точностью 39 знаков, она мгновенно отвергает запрос и возвращает ошибку, прерывая транзакцию проведения документа.
Рассмотрим ситуацию, с которой часто сталкиваются администраторы. Пытаясь локализовать проблему, базу данных выгружают в файл резервной копии (.dt), разворачивают локально (в файловом варианте) и пробуют провести документ там. В файловом варианте СУБД SQL Server не участвует, поэтому документ проводится без ошибок.
После этого администратор загружает исправленную базу обратно на SQL-сервер и думает, что проблема решена. Однако при первом же обращении к механизму расчета итогов СУБД снова выдает ошибку превышения разрядности. Это доказывает, что физическая структура данных не повреждена, а виновником является исключительно некорректная генерация SQL-запросов самой платформой 8.3.12.1412.
Единственным надежным и долгосрочным решением является обновление технологической платформы. Фирма «1С» оперативно признала данный релиз дефектным и отозвала его из списка рекомендованных к установке.
Для устранения ошибки выполните следующие действия:
8.3.12.1469. Тем не менее, рекомендуется устанавливать более современные стабильные сборки ветки 8.3 (например, 8.3.13.1690 или актуальные релизы LTS).Агент сервера 1С:Предприятия.После обновления платформы генерация запросов к СУБД нормализуется, разрядность полей итогов будет корректно укладываться в стандартные 38 знаков, и документы начнут проводиться в штатном режиме.
Если по каким-то причинам обновить платформу прямо сейчас невозможно (например, требуется длительное согласование с ИТ-отделом или обновление должно происходить строго по регламенту), разработчики могут прибегнуть к временному изменению текста проблемных запросов.
Проанализируем ситуацию: нам необходимо принудительно ограничить разрядность числового поля до передачи его в секцию расчета итогов. Для этого используется конструкция встроенного языка запросов ВЫРАЗИТЬ. Рассмотрим пример решения:
Допустим, у нас есть исходный проблемный запрос:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
Продажи.СуммаОборота КАК СуммаОборота
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
ИТОГИ
СУММА(СуммаОборота)
ПО
Контрагент
Чтобы избежать переполнения разрядности при суммировании на стороне SQL Server, мы должны явно указать точность для суммируемого поля. Изменим запрос следующим образом:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
ВЫРАЗИТЬ(Продажи.СуммаОборота КАК ЧИСЛО(15, 2)) КАК СуммаОборота
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
ИТОГИ
СУММА(СуммаОборота)
ПО
Контрагент
Применение конструкции ВЫРАЗИТЬ(Поле КАК Число(15, 2)) гарантирует СУБД, что размерность данных жестко ограничена. В результате SQL Server построит корректный план запроса без попыток назначить итоговому полю критическую разрядность в 39 знаков.
Отказ от использования версии платформы 8.3.12.1412 обоснован не только ошибкой работы с MS SQL Server. Данный релиз содержал целый ряд других критических уязвимостей, которые делают его непригодным для промышленной эксплуатации:
ПОЛНОЕ СОЕДИНЕНИЕ (FULL JOIN) приводило к аварийному завершению работы с системной ошибкой вида ERROR: column "fld..." does not exist. Платформа теряла физические имена колонок во временных таблицах.BEX / код исключения c0000005).В связи с этим, замена релиза платформы является единственным комплексным и безопасным выходом для обеспечения стабильной работы бизнес-приложений фирмы 1С.