Как найти и устранить причину периодической аномальной нагрузки на tempdb в SQL Server при работе с 1С?

Системный администратор 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При администрировании высоконагруженных систем 1С:Предприятие на базе MS SQL Server администраторы часто сталкиваются с ситуацией, когда база данных tempdb начинает вести себя аномально. Она может резко увеличиваться в размерах, занимая все дисковое пространство, или создавать огромную нагрузку на дисковую подсистему (IO), что приводит к "тормозам" во всей системе. Особенно сложно диагностировать такие проблемы, когда они возникают периодически (например, раз в день) и исчезают до того, как удается поймать "виновника".

В этой статье мы подробно разберем методику поиска причин такой нагрузки, проанализируем поведение SQL Server и рассмотрим инструменты, которые помогут выявить проблемные запросы или настройки.

Понимаем природу нагрузки: Пользовательские и Внутренние объекты

Прежде чем искать "вредителя", давайте разберемся, чем именно может быть занят tempdb. В контексте 1С нагрузку можно разделить на три основные категории:

  1. Явные временные таблицы (User Objects). Это таблицы, которые 1С создает явно (имена вида #tt...). Они используются при проведении документов, в сложных отчетах и запросах. Если Технологический журнал (ТЖ) не показывает сверхтяжелых запросов, возможно, проблема не здесь.
  2. Внутренние объекты (Internal Objects). Это скрытые структуры, которые SQL Server создает сам для выполнения запросов. Сюда входят таблицы для сортировки (Sort), хэширования (Hash Match) и промежуточных вычислений (Spool). Именно они часто являются невидимой причиной проблем.
  3. Версионирование (Version Store). Если включен режим READ_COMMITTED_SNAPSHOT (RCSI), копии изменяемых данных хранятся в tempdb.

Рассмотрим сценарии диагностики для каждой из этих причин.

Сценарий 1: Проблемы статистики и нехватка памяти (Internal Objects)

Одной из самых частых причин резких всплесков нагрузки на tempdb, которые трудно отловить обычными средствами 1С (консоль, ТЖ), является устаревшая статистика SQL Server.

Суть проблемы: Когда SQL Server строит план выполнения запроса, он опирается на статистику. Если статистика говорит, что запрос вернет 100 строк, сервер выделяет под эту операцию, например, 1 МБ памяти. Но если статистика устарела и по факту возвращается 1 000 000 строк, выделенной памяти не хватает.

В этот момент происходит событие, называемое Spill to TempDB (сброс в tempdb). Сервер вынужден сбрасывать промежуточные данные (сортировки, хэш-таблицы) на диск в tempdb. Это порождает:

Как диагностировать: Поскольку в старых версиях SQL Server (например, 2008/2012) нет Query Store, нам поможет SQL Server Profiler. Настроим трассировку, включив следующие события из раздела Errors and Warnings:

Если во время "тормозов" вы видите эти события, значит, причина не в сложности кода 1С, а в том, что SQL Server ошибается с оценкой необходимой памяти. Решением может стать обновление статистики:


UPDATE STATISTICS _AccRg12345 WITH FULLSCAN; -- Пример для конкретной таблицы
-- Или обслуживание всей базы
EXEC sp_updatestats;

Сценарий 2: "Талантливые" пользователи и сложные отборы

Вторая распространенная причина — действия пользователей в списках документов или журналах. Даже в обычных формах (ОФ) и тем более в управляемых (УФ), пользователи имеют возможность настраивать отборы.

Механизм возникновения проблемы: Пользователь открывает журнал документов (например, "Реализация товаров и услуг") и устанавливает отбор по реквизиту составного типа или через точку (разыменовывая поля). Например: Контрагент.ОсновнойМенеджер.ФизЛицо ПОДОБНО "%Иванов%".

Особенно опасны отборы в сочетании с RLS (Row Level Security — ограничение прав доступа на уровне записей). В этом случае платформа 1С генерирует SQL-запрос, который содержит:

  1. Множество соединений (JOIN) с таблицами ссылочных типов.
  2. Подзапросы для проверки прав доступа (RLS).

Даже если запрос выбирает TOP 20 строк для отображения на экране, для выполнения условий фильтрации и RLS серверу может потребоваться просканировать миллионы записей, создать временные хэш-таблицы в tempdb и только потом выдать результат. В консоли 1С такой запрос может не выглядеть как "зависший", так как он может выполняться порциями, но нагрузку на диск он создает постоянную.

Решение: Анализировать планы запросов, попадающих в топы по CPU и IO. Обращать внимание на запросы к таблицам _DocumentJournal (Журналы документов) или основным документам с большим количеством JOIN.

Сценарий 3: Зависшие транзакции и Версионирование

Если в базе используется режим изоляции снимков (RCSI), который является стандартом де-факто для 1С, причиной роста tempdb могут быть незакрытые транзакции.

Как это работает: 1. Пользователь запускает отчет или обработку, которая открывает транзакцию. 2. Происходит ошибка, или окно с вопросом, или сеанс "зависает", но транзакция остается открытой (статус SLEEPING, но open_transaction_count > 0). 3. SQL Server не может удалить старые версии строк из tempdb (Version Store), так как они теоретически могут понадобиться этой старой транзакции. 4. Все изменения данных, которые делают другие пользователи, начинают копиться в tempdb. Файл растет бесконтрольно.

Диагностика: Используйте команду для поиска старейшей активной транзакции:

DBCC OPENTRAN;

Также полезно проверить сессии, которые потребляют больше всего места в tempdb. Для этого можно использовать следующий запрос к системным представлениям (работает на версиях SQL 2005+):


SELECT
    t.session_id,
    t.request_id,
    exec_context_id,
    ot.task_state,
    r.command,
    -- Потребление места пользовательскими объектами (в страницах)
    t.user_objects_alloc_page_count, 
    t.user_objects_dealloc_page_count,
    -- Потребление места внутренними объектами (сортировки, хэши)
    t.internal_objects_alloc_page_count, 
    t.internal_objects_dealloc_page_count,
    es.login_name,
    es.program_name,
    st.text AS QueryText
FROM sys.dm_db_task_space_usage t
JOIN sys.dm_os_tasks ot ON t.session_id = ot.session_id AND t.request_id = ot.request_id
JOIN sys.dm_exec_sessions es ON t.session_id = es.session_id
LEFT JOIN sys.dm_exec_requests r ON t.session_id = r.session_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) st
WHERE t.session_id > 50
ORDER BY (t.internal_objects_alloc_page_count + t.user_objects_alloc_page_count) DESC;

Этот скрипт покажет, какая именно сессия "накачивает" tempdb прямо сейчас. Обратите внимание на колонку internal_objects_alloc_page_count. Если она велика — это подтверждает гипотезу о проблемах с планом запроса (сортировки/хэши). Для визуализации этих данных и интерактивного анализа текущей нагрузки можно использовать обработку для мониторинга и анализа работы SQL Server.

Рекомендации по настройке инфраструктуры tempdb

Чтобы минимизировать влияние таких проблем, проверим настройки самого SQL Server, которые считаются "золотым стандартом" для работы с 1С:

  1. Количество файлов данных. Рассмотрите возможность разделения tempdb на несколько файлов данных (обычно рекомендуют количество файлов, равное количеству ядер процессора, но не более 8). Это снижает конкуренцию за страницы распределения (GAM/SGAM contention).
  2. Одинаковый размер и авторост. Все файлы данных tempdb должны быть одного размера и иметь одинаковые параметры автоувеличения. Это важно для того, чтобы алгоритм Proportional Fill равномерно распределял нагрузку.
  3. Фиксированный размер. Если позволяет место, задайте файлам tempdb сразу большой размер (например, чтобы суммарно они занимали 20-30 Гб или больше, в зависимости от обычной пиковой нагрузки). Это предотвратит постоянные операции расширения файлов в рабочее время.
  4. Мгновенная инициализация (IFI). Убедитесь, что у учетной записи службы SQL Server есть право "Perform Volume Maintenance Tasks" в локальных политиках безопасности Windows. Это позволит файлам расти мгновенно, не заполняя новое место нулями.

Итог: План действий

Если вы снова столкнетесь с аномальной нагрузкой, действуйте по следующему алгоритму:

  1. Запустите скрипт мониторинга использования tempdb (приведен выше), чтобы найти конкретную сессию.
  2. Если виновник найден, посмотрите текст его запроса. Если это системный запрос или простой список — скорее всего, проблема в плане выполнения.
  3. Проверьте DBCC OPENTRAN на наличие зависших старых транзакций.
  4. Запустите Profiler с событиями Warnings (Sort/Hash), чтобы подтвердить нехватку памяти для запроса.
  5. В качестве временной меры часто помогает обновление статистики по задействованным таблицам, но для долгосрочного решения может потребоваться оптимизация кода 1С (упрощение запросов, RLS) или настройка сервера.
← На главную