Перевод старой, но проверенной временем платформы 1С:Предприятие 7.7 с файлового режима (DBF) на клиент-серверный (MS SQL Server) — это классическая задача, с которой до сих пор сталкиваются системные администраторы и разработчики при поддержке исторических баз данных. На первый взгляд, процесс выглядит стандартно: создается пустая база на сервере, выполняется выгрузка данных в файл .dat и последующая загрузка в SQL-версию платформы. Все проходит без ошибок, но при первой же попытке провести, перепровести или отменить проведение любого документа система намертво зависает.
При этом на стороне сервера баз данных начинается лавинообразный процесс: системная база данных tempdb стремительно растет в размерах, поглощая все свободное дисковое пространство гигабайт за гигабайтом, пока сервер полностью не остановится. Проанализируем эту ситуацию, выясним глубокие технические причины такого поведения СУБД и платформы, а также разберем по шагам три практических способа решения этой проблемы.
Для того чтобы понять, что происходит в момент зависания, нам необходимо заглянуть «под капот» взаимодействия платформы 1С 7.7 и СУБД. Лучшим инструментом для этого является трассировка запросов через SQL Server Profiler. При попытке провести документ в 1С и последующем зависании интерфейса, Profiler фиксирует бесконечное выполнение одной и той же системной хранимой процедуры.
Типичный запрос, на котором останавливается выполнение, выглядит следующим образом:
exec _1sp_RA635_ClearRecalcDocActs ' I4U11 ','2018-10-29 00:00:00','2018-10-26 00:00:00',1,0,1
Проанализируем параметры этого вызова. Имя процедуры указывает на то, что выполняется очистка движений (таблицы итогов и движений регистров накопления, в данном примере — регистра RA635) перед проведением или при отмене проведения документа. В параметрах передаются идентификатор документа и две даты, ограничивающие период пересчета. Обратите внимание на даты: '2018-10-29 00:00:00' и '2018-10-26 00:00:00'. Они передаются в СУБД в виде текстовых строк стандартного формата YYYY-MM-DD HH:MM:SS.
Основная проблема кроется в особенностях интерпретации текстового представления дат типом данных datetime в СУБД MS SQL Server (начиная с версии SQL Server 2005 и выше).
Вопреки распространенному мнению, формат записи даты с дефисами YYYY-MM-DD не является абсолютно универсальным для устаревшего типа данных datetime в SQL Server. Его правильное распознавание напрямую зависит от языковых настроек сессии пользователя СУБД, под которым 1С 7.7 подключается к базе данных (параметр DATEFORMAT).
Рассмотрим детально, как это работает:
'2018-10-29', SQL Server пытается разобрать ее в соответствии с правилом YYYY-DD-MM (поскольку дефисы заставляют СУБД использовать локальные настройки сессии).29 на место месяца СУБД понимает, что 29-го месяца не существует, и генерирует внутреннюю ошибку преобразования типов: "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value" (Преобразование типа данных varchar в тип данных datetime привело к выходу значения за пределы допустимого диапазона).В современных конфигурациях и платформах (например, в 1С 8.3) возникновение такой ошибки привело бы к мгновенному прерыванию транзакции и возврату понятного сообщения пользователю. Но архитектура платформы 1С 7.7 работает иначе:
_1sp_RA..._ClearRecalcDocActs) обработка записей часто происходит в циклах или через временные таблицы в базе tempdb.tempdb (версии строк, временные объекты, журналы). Это приводит к лавинообразному забиванию диска временными файлами СУБД.Самый простой, быстрый и безопасный способ устранить эту проблему — изменить языковые настройки для учетной записи (Login) в MS SQL Server, под которой авторизуется платформа 1С.
Выполним следующие шаги:
sa).Security (Безопасность) -> Logins (Имена входа).sa, либо специально созданный пользователь, например, usr1c). Щелкните по нему правой кнопкой мыши и выберите Properties (Свойства).После смены языка на English формат трактовки дат для этого пользователя автоматически изменится на MDY. Теперь SQL Server будет корректно распознавать строку формата YYYY-MM-DD как год-месяц-день, процедура выполнится за сотые доли секунды, транзакция успешно закроется, а база tempdb останется в стабильном состоянии.
Бывают ситуации, когда изменить глобальный язык по умолчанию для пользователя SQL невозможно (например, под этой же учетной записью работают сторонние интеграционные сервисы, завязанные на русскоязычный формат выгрузки дат или системных сообщений). В таком случае мы можем перехватывать момент подключения 1С 7.7 к СУБД и принудительно задавать формат обработки дат на уровне конкретной сессии.
Для этого мы создадим системный триггер на вход (Logon Trigger) в SQL Server. Разберем этот пример кода:
CREATE TRIGGER [1C_DateFormat_Fix]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN() = 'Имя_Вашего_Пользователя_1С'
BEGIN
EXEC('SET DATEFORMAT ymd;');
END;
END;
Замените 'Имя_Вашего_Пользователя_1С' на реальный логин пользователя СУБД, под которым работает ваша база 1С 7.7. Этот триггер при каждом успешном подключении пользователя будет автоматически выполнять команду SET DATEFORMAT ymd;, что гарантирует правильное распознавание дат СУБД без изменения глобального языка интерфейса системы.
В редких случаях проблема может усугубляться тем, что в исходной файловой базе (DBF) физически присутствуют «битые» или некорректные даты документов или их движений. Например, даты вида 00.00.0000, пустые значения или некорректные даты из далекого прошлого/будущего (например, 01.01.0100 или 31.12.9999).
Диапазон допустимых дат для типа данных datetime в MS SQL Server строго ограничен: от 1 января 1753 года до 31 декабря 9999 года. Любая дата, выходящая за эти рамки (например, «нулевая» дата), вызывает ошибку преобразования типов на стороне сервера.
Для исправления таких ошибок рекомендуется провести аудит данных перед выгрузкой:
1CJOURN и таблицы движений регистров (начинаются с префикса RA), отсортировав колонки с датами по возрастанию и убыванию, чтобы выявить некорректные или пустые значения и вручную исправить их на валидные даты.Применение одного из описанных выше способов (в первую очередь — изменения языка по умолчанию на English для SQL-пользователя) гарантированно решает проблему «зависания» платформы 1С 7.7 и обеспечивает стабильную и быструю работу переведенной базы данных в клиент-серверном режиме.