При переходе с файловой версии «1С:Предприятия» на клиент-серверный вариант работы системные администраторы и разработчики часто сталкиваются с неожиданным поведением СУБД. Одной из наиболее острых проблем является лавинообразный рост системной базы данных tempdb на MS SQL Server. Особенно ярко это проявляется при выполнении ресурсоемких операций, таких как создание первоначального образа подчиненного узла распределенной информационной базы (РИБ) с установленными фильтрами регистрации.
Представьте ситуацию: рабочая база данных имеет скромный размер около 2.5 ГБ, однако при попытке сформировать образ РИБ база tempdb разрастается до 70–80 ГБ, полностью забивает дисковое пространство, после чего СУБД аварийно завершает работу, а процесс создания образа прерывается. При этом тестирование и исправление (ТИИ) не выявляет никаких ошибок в структуре данных. Выясним, почему это происходит, и подробно разберем эффективные методы локализации и решения этой проблемы.
Для начала проанализируем внутренние механизмы СУБД и платформы «1С:Предприятие», которые приводят к подобному поведению системы:
Read Committed Snapshot Isolation. При создании начального образа запускается одна очень длинная транзакция на чтение. Если в этот момент в центральной базе продолжают работать пользователи или выполняются фоновые задания, SQL Server вынужден сохранять старые версии изменяемых данных в специальном хранилище версий (Version Store), которое физически находится именно в tempdb. Пока транзакция создания образа не завершится, эти версии строк не могут быть очищены, что вызывает лавинообразный рост дискового пространства.tempdb. Например, перекрестное соединение крупных регистров без индексов способно моментально раздуть базу временных таблиц до десятков гигабайт.Sort) или хеширования (Hash Match), сбрасывая промежуточные результаты на диск в tempdb (так называемые Hash/Sort Spills).Прежде чем предпринимать радикальные шаги, нам необходимо локализовать проблему и понять, какая именно сессия или какие временные таблицы утилизируют дисковое пространство. Для этого выполним детальный мониторинг системной базы данных tempdb с помощью специализированных скриптов.
Рассмотрим первый скрипт, который позволяет определить активные сессии, потребляющие наибольший объем дискового пространства в tempdb:
SELECT
s.host_name,
s.writes,
usage.session_id,
usage.user_objects_alloc_page_count,
usage.user_objects_dealloc_page_count,
usage.internal_objects_alloc_page_count,
usage.internal_objects_dealloc_page_count
FROM
sys.dm_db_session_space_usage usage
LEFT JOIN sys.dm_exec_sessions s ON s.session_id = usage.session_id
ORDER BY
(user_objects_alloc_page_count + internal_objects_alloc_page_count) DESC;
Этот запрос наглядно покажет нам ID сессии 1С, которая активно выделяет страницы (alloc page count) под пользовательские и внутренние объекты. Если мы обнаружим аномально высокие показатели, мы сможем сопоставить этот session_id с сеансом в консоли администрирования кластера 1С.
Для анализа конкретных временных таблиц, созданных внутри tempdb, и оценки их физического размера в мегабайтах, выполним следующий полезный скрипт:
SELECT
obj.name AS Table_Name,
SUM(ps.reserved_page_count) * 8 / 1024 AS Reserved_MB,
SUM(used_page_count) * 8 / 1024 AS Total_MB,
SUM(
CASE
WHEN (index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
ELSE lob_used_page_count + row_overflow_used_page_count
END
) * 8 / 1024 AS Data_MB,
SUM (
CASE
WHEN (index_id >= 2) THEN in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count
ELSE 0
END
) * 8 / 1024 AS Index_MB,
SUM(CASE WHEN (index_id < 2) THEN row_count ELSE 0 END) AS Rows_Count
FROM
tempdb.sys.tables obj
LEFT JOIN tempdb.sys.dm_db_partition_stats ps ON ps.object_id = obj.object_id
GROUP BY
obj.object_id, obj.name
ORDER BY
Total_MB DESC;
Проанализировав результаты, мы поймем, создаются ли миллионы мелких таблиц, либо СУБД раздувает одну-две гигантские таблицы из-за отсутствия правильных условий соединения.
Часто СУБД строит неверный план выполнения из-за «залипшего» старого кэша планов запросов. Перед запуском процедуры создания начального образа РИБ обязательно выполним регламентные операции на уровне SQL-сервера.
Разберем последовательность действий:
EXEC sp_updatestats;
DBCC FREEPROCCACHE;
Если во время выгрузки образа базы в ней параллельно работают другие пользователи, Version Store в tempdb неизбежно начнет расти. Самый простой способ избежать этого — выполнять создание образа РИБ в монопольном режиме, когда в базе нет активных транзакций, либо временно перевести базу в обычный режим блокировок (без версионирования строк).
Рассмотрим, как отключить версионирование строк перед процедурой:
ALTER DATABASE [Имя_Вашей_Базы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
READ_COMMITTED_SNAPSHOT:
ALTER DATABASE [Имя_Вашей_Базы] SET READ_COMMITTED_SNAPSHOT OFF;
ALTER DATABASE [Имя_Вашей_Базы] SET MULTI_USER;
ON.Если штатный механизм платформы 1С СоздатьНачальныйОбраз() продолжает аварийно завершаться из-за нехватки дискового пространства под tempdb, мы можем прибегнуть к проверенному альтернативному сценарию создания подчиненного узла. Этот метод полностью исключает нагрузку на tempdb во время инициализации РИБ.
Разберем этот процесс по шагам:
// Получим ссылку на узел, который должен стать главным для этой базы
СсылкаНаГлавныйУзел = ПланыОбмена.ВашПланОбмена.НайтиПоКоду("КодЦентральногоУзла");
Если ЗначениеЗаполнено(СсылкаНаГлавныйУзел) Тогда
ПланыОбмена.УстановитьГлавныйУзел(СсылкаНаГлавныйУзел);
Сообщить("База успешно преобразована в подчиненный узел РИБ.");
Иначе
Сообщить("Не удалось найти главный узел по указанному коду!");
КонецЕсли;
tempdb.Этот метод гарантирует 100% результат даже на базах объемом в сотни гигабайт, поскольку исключает необходимость выполнения колоссальных по объему выборок данных за один проход.
Чтобы минимизировать риски падения СУБД при любых тяжелых операциях, важно правильно настроить саму базу данных tempdb на уровне операционной системы и MS SQL Server:
tempdb, равное числу логических ядер процессора вашего сервера (но не более 8 файлов). Все файлы должны иметь строго одинаковый начальный размер и одинаковые параметры автоприроста. Это позволит SQL Server использовать алгоритм пропорционального заполнения (Proportional Fill) и существенно повысит параллелизм работы.tempdb в процентах (по умолчанию часто стоит 10%). Установите фиксированный прирост в мегабайтах (например, по 512 МБ или 1024 МБ). Это предотвратит фрагментацию файлов и снизит накладные расходы СУБД на постоянное динамическое выделение дискового пространства..mdf) и логов (.ldf) базы tempdb на выделенный высокоскоростной массив дисков (рекомендуется использовать современные твердотельные накопители NVMe или SSD), отдельный от дисков с рабочими базами данных.И наконец, обратим внимание на версию используемой технологической платформы. В старых релизах (таких как 8.3.9) присутствовали внутренние утечки памяти и неоптимальные алгоритмы работы с СУБД при выгрузке пакетов данных РИБ. Настоятельно рекомендуется обновить платформу «1С:Предприятие» до актуальных версий ветки 8.3.16 и выше, в которых разработчики 1С провели глобальную оптимизацию механизмов обмена данными и минимизировали использование временных таблиц при формировании начальных образов.