1С и MS SQL Server изнутри: путь запроса, блокировки, обслуживание базы
Содержание
1С на SQL Server работает по трёхзвенной схеме: пользователь общается только с кластером серверов 1С, а с базой данных говорит рабочий процесс rphost. Он переводит запросы встроенного языка в T-SQL, отправляет их в MS SQL Server и держит транзакции. Поэтому архитектура, блокировки и производительность зависят сразу от двух систем: от настроек кластера 1С и от настроек СУБД.
Типичная ситуация: в конце месяца закрытие идёт три часа, а менеджеры ловят Превышено максимальное время ожидания предоставления блокировки. Админ добавляет память серверу, но ничего не меняется. Причина обычно в другом звене: в плане запроса, устаревшей статистике или режиме блокировок конфигурации. Чтобы найти узкое место, нужно понимать, как устроена связка целиком.
Как устроена связка сервера 1С и SQL Server
В клиент-серверном варианте участвуют три уровня. Клиент (толстый, тонкий или веб) не подключается к SQL Server напрямую. Он видит только кластер 1С.
Путь соединения:
- 🖥️ Клиент обращается к агенту сервера
ragent— по умолчанию порт1540. - 🧭 Агент передаёт его менеджеру кластера
rmngr— порт1541. - ⚙️ Менеджер назначает рабочий процесс
rphost. Диапазон портов рабочих процессов задаётся в свойствах рабочего сервера, по умолчанию1560:1591. - 🗄️ Рабочий процесс открывает соединение с SQL Server и выполняет запросы к базе.
Строку подключения к СУБД хранят свойства информационной базы в кластере: сервер баз данных, тип СУБД MSSQLServer, имя базы и пользователь SQL Server. Их видно в консоли администрирования серверов 1С, в свойствах базы.
Где что хранится
| Что | Где живёт | Чем управляется |
|---|---|---|
| Данные (справочники, документы, регистры) | База на SQL Server | SQL Server |
| Сеансы, соединения, управляемые блокировки | Менеджер кластера 1С | Кластер 1С |
| Кэш метаданных, сеансовые данные | Рабочие процессы и каталог кластера | Кластер 1С |
| Конфигурация | Служебные таблицы в той же базе SQL | Платформа |
Если сервер 1С и SQL Server стоят на одной машине, трафик между ними идёт через локальные протоколы, без сети. Это быстрее, но они начинают делить память и процессор. Поэтому ограничение памяти SQL Server становится обязательным, об этом ниже.
Во что 1С превращает запросы: таблицы, T-SQL и план выполнения
Платформа не хранит объекты под их именами. Справочник «Номенклатура» в SQL Server — это таблица вида _Reference45, реквизит — колонка _Fld1234. Ссылки хранятся как binary(16) в полях _IDRRef, у объектов есть поле версии _Version, пометка удаления _Marked, у документов — _Posted.
Соответствие имён можно получить из самой 1С функцией ПолучитьСтруктуруХраненияБазыДанных(). Без неё в логах SQL Server не разобраться, какой регистр тормозит.
Структура = ПолучитьСтруктуруХраненияБазыДанных(, Истина);
Для Каждого Строка Из Структура Цикл
Сообщить(Строка.Метаданные + " = " + Строка.ИмяТаблицыХранения);
КонецЦикла;
Второй параметр Истина возвращает имена в терминах СУБД. Код выполняется на сервере с правами администратора.
Как запрос 1С становится T-SQL
Рабочий процесс транслирует текст запроса в T-SQL. Несколько последствий, которые видны в профилировщике:
- 📊 Виртуальные таблицы
ОстаткииОстаткиИОборотыразворачиваются в подзапросы к таблицам итогов регистров (_AccumRgT…) и к таблице движений. Если параметр периода задан, читаются итоги, а не все движения. - 🧮 Временные таблицы
ПОМЕСТИТЬсоздаются вtempdbкак#tt…. Отсюда нагрузка наtempdbв тяжёлых отчётах. - 🔁 Запросы уходят параметризованными, SQL Server кэширует их планы и использует повторно.
- 🔐 Если включены ограничения доступа к данным (RLS), к запросу добавляются условия, и план может заметно усложниться.
Почему план бывает плохим
SQL Server строит план по статистике распределения данных. Статистика устарела — оптимизатор ошибается в числе строк и выбирает сканирование вместо поиска по индексу или неудачный порядок соединений.
Частые причины медленного плана со стороны 1С:
- ❌ Отбор по полю, для которого нет индекса. В конфигураторе у реквизита есть свойство «Индексировать».
- ❌ Соединение с подзапросом вместо временной таблицы — оптимизатор плохо оценивает подзапросы.
- ❌ Отбор по реквизиту через точку («Контрагент.ИНН») — каждое разыменование добавляет соединение.
- ❌ Условие на виртуальную таблицу вынесено в
ГДЕ, а не в параметры таблицы. Тогда сначала читается весь остаток, потом фильтруется.
Транзакции и блокировки 1С на SQL Server
Запись и проведение документа идут в транзакции. Пока она открыта, изменённые строки заблокированы. От того, кто ставит блокировки, зависит, сколько пользователей могут работать параллельно.
Режимы управления блокировками
Режим задаёт свойство конфигурации «Режим управления блокировкой данных». Значений три: «Автоматический», «Управляемый», «Автоматический и управляемый».
| Режим | Кто блокирует | Последствия |
|---|---|---|
| Автоматический | SQL Server, высокий уровень изоляции транзакций | Блокировки шире нужного, чтение ждёт запись, частые взаимоблокировки |
| Управляемый | Менеджер блокировок кластера 1С + SQL Server | Блокируются только нужные данные, чтение не ждёт запись |
| Автоматический и управляемый | Задаётся у каждого объекта метаданных | Переходный вариант для доработанных старых конфигураций |
Типовые конфигурации на 8.3 (Бухгалтерия 3.0, ЗУП 3.1, УТ 11, ERP) работают в управляемом режиме. В этом режиме при работе с SQL Server и режиме совместимости 8.3 платформа использует для базы версионирование строк (READ_COMMITTED_SNAPSHOT). Чтение видит последнюю зафиксированную версию строки и не ждёт пишущую транзакцию.
Код проведения в управляемом режиме сам объявляет, что блокировать, объектом БлокировкаДанных:
Блокировка = Новый БлокировкаДанных;
Элемент = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
Элемент.Режим = РежимБлокировкиДанных.Исключительный;
Элемент.УстановитьЗначение("Склад", Склад);
Блокировка.Заблокировать();
Здесь блокируются остатки только одного склада, а не весь регистр.
Ошибки блокировок и что они значат
- ⏳
Превышено максимальное время ожидания предоставления блокировки— сработал таймаут управляемой блокировки 1С. Кто-то долго держит те же данные. Ищите длинную транзакцию. - 💥
Конфликт блокировок при выполнении транзакциис текстом SQL Server про взаимоблокировку и «жертву» — deadlock: две транзакции ждут друг друга, SQL Server прерывает одну. - 🐢
Истекло время ожидания запроса на блокировкуот провайдера SQL — ожидание блокировки на уровне СУБД, а не 1С. Типично для автоматического режима или эскалации блокировок.
Настройка производительности SQL Server под 1С
Настройки по умолчанию у SQL Server рассчитаны на универсальную нагрузку. Для базы 1С с короткими транзакциями и множеством пользователей их стоит поправить.
Память
Параметр max server memory ограничивает буферный пул SQL Server. Без него СУБД со временем займёт почти всю память, и при общем сервере рабочим процессам 1С не хватит места.
Ориентир расчёта: из общего объёма вычесть память под ОС (4–6 ГБ) и под процессы rphost, если они на той же машине. Пример: сервер 64 ГБ, ОС — 4 ГБ, 1С в пике берёт 16 ГБ. Остаётся 64 − 4 − 16 = 44 ГБ для max server memory.
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'max server memory (MB)', 45056; RECONFIGURE;
45056 МБ — это 44 ГБ (44 × 1024).
Со стороны 1С расход памяти ограничивается в свойствах рабочего сервера: «Критический объём памяти процессов» и «Безопасный расход памяти за один вызов». Они защищают сервер от одного тяжёлого отчёта, который съедает всю память.
Параллелизм
Для 1С обычно рекомендуют max degree of parallelism = 1. Короткие запросы учётной системы не выигрывают от параллельных планов, а ожидания CXPACKET растут.
EXEC sp_configure 'max degree of parallelism', 1; RECONFIGURE;
Если в базе много тяжёлых аналитических отчётов, вместо MAXDOP = 1 можно оставить 2–4 и поднять cost threshold for parallelism до 50 и выше. Тогда параллельно пойдут только действительно тяжёлые запросы.
Диски и tempdb
Что даёт заметный выигрыш:
- 💾 Файлы данных, журнал транзакций и
tempdb— на разных быстрых дисках (SSD или NVMe). - 📁 Для
tempdb— несколько файлов данных одинакового размера, обычно по числу ядер, но не больше 8. - 📏 Автоприращение задавать в мегабайтах (например, 512 МБ), а не в процентах.
- ⚡ В схеме электропитания Windows выбрать «Высокая производительность».
Модель восстановления
| Модель | Когда подходит | Риски |
|---|---|---|
| Simple | Потеря данных за день допустима, бэкап раз в сутки | Восстановление только на момент полной копии |
| Full | Нужно восстанавливать на любой момент времени | Журнал растёт, если не делать резервные копии журнала |
При модели Full без регулярного бэкапа журнала файл .ldf растёт до заполнения диска, после чего база перестаёт принимать изменения.
Регламентное обслуживание базы данных 1С на SQL Server
Без обслуживания база деградирует: индексы фрагментируются, статистика устаревает, планы портятся. Регламент настраивают планами обслуживания SQL Server (Maintenance Plans) или заданиями агента SQL Server на ночное время.
Базовый набор операций:
- 🔄 Обновление статистики — ежедневно. Самая полезная операция для 1С.
- 🧹 Очистка процедурного кэша — сразу после обновления статистики, чтобы планы перестроились по новым данным.
- 🧱 Дефрагментация индексов — раз в неделю: при фрагментации 5–30 % реорганизация, выше 30 % перестроение.
- 🩺 Проверка целостности
DBCC CHECKDB— раз в неделю. - 💾 Резервное копирование — полная копия ежедневно, при модели Full плюс копии журнала каждые 15–60 минут.
USE [buh];
EXEC sp_updatestats;
DBCC FREEPROCCACHE;
DBCC FREEPROCCACHE очищает кэш планов всего экземпляра SQL Server, а не одной базы. Несколько минут после неё запросы будут работать медленнее, пока планы строятся заново. Запускайте ночью, когда пользователей нет.
Проверить фрагментацию индексов:
SELECT OBJECT_NAME(s.object_id) AS tbl, i.name AS idx,
s.avg_fragmentation_in_percent, s.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') s
JOIN sys.indexes i ON i.object_id = s.object_id AND i.index_id = s.index_id
WHERE s.page_count > 1000
ORDER BY s.avg_fragmentation_in_percent DESC;
Маленькие индексы (меньше 1000 страниц) дефрагментировать смысла нет — выигрыша не будет.
Обслуживание со стороны 1С
У регистров накопления и бухгалтерии есть итоги. Их актуальность важна для скорости остатков. Управлять итогами можно через Все функции → Стандартные → Управление итогами: установить период рассчитанных итогов, пересчитать итоги, включить разделение итогов.
Разделение итогов снижает конкуренцию за одни и те же строки таблицы итогов при одновременном проведении. Для регистров с интенсивной записью его стоит держать включённым.
Не делайте регулярное сжатие базы (SHRINK). Оно фрагментирует индексы, а база всё равно вырастет снова. Сжатие оправдано только разово, после удаления большого объёма данных.
Диагностика проблем производительности и анализ логов
Начинайте с вопроса: где время — в 1С или в СУБД? Ответ дают два источника: технологический журнал 1С и динамические представления SQL Server.
Технологический журнал 1С
Журнал включается файлом logcfg.xml в каталоге conf платформы на сервере 1С (например, C:\Program Files\1cv8\conf). Платформа подхватывает изменения файла без перезапуска службы.
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
<log location="D:\techlog" history="24">
<event><eq property="name" value="TLOCK"/></event>
<event><eq property="name" value="TTIMEOUT"/></event>
<event><eq property="name" value="TDEADLOCK"/></event>
<event><eq property="name" value="EXCP"/></event>
<event>
<eq property="name" value="DBMSSQL"/>
<gt property="duration" value="1000000"/>
</event>
<property name="all"/>
</log>
<plansql/>
</config>
Что ловят события:
- 🔒
TLOCK— установка управляемых блокировок,TTIMEOUT— таймауты,TDEADLOCK— взаимоблокировки. - 🐌
DBMSSQL— запросы к SQL Server. Фильтр поdurationоставляет только долгие: в 8.3 длительность измеряется в микросекундах, 1 000 000 — одна секунда. - 📜 Элемент
<plansql/>добавляет в события планы запросов. - ⚠️
EXCP— исключения, в том числе ошибки СУБД.
history="24" хранит логи 24 часа. Технологический журнал с DBMSSQL быстро растёт, поэтому каталог должен быть на диске с запасом места.
Не оставляйте полный журнал включённым надолго. На нагруженном сервере он сам становится нагрузкой на диск. Собрали данные за проблемный период — отключите.
Что смотреть в SQL Server
Кто кого блокирует прямо сейчас:
SELECT r.session_id, r.blocking_session_id, r.wait_type,
r.wait_time, DB_NAME(r.database_id) AS db, t.text
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.blocking_session_id <> 0;
Накопленные ожидания экземпляра показывает sys.dm_os_wait_stats. Как их читать:
| Преобладающее ожидание | О чём говорит |
|---|---|
PAGEIOLATCH_* | Данные не помещаются в память или медленные диски |
WRITELOG | Медленный диск журнала транзакций |
LCK_M_* | Ожидание блокировок СУБД |
CXPACKET, CXCONSUMER | Параллельные планы, проверьте MAXDOP |
SOS_SCHEDULER_YIELD | Нехватка процессора или тяжёлые сканирования |
Для длительной записи событий в самом SQL Server используйте Extended Events: сеанс с событиями долгих запросов и отчётом о взаимоблокировках (xml_deadlock_report). Старый SQL Profiler на рабочем сервере лучше не запускать — он сам грузит СУБД.
Порядок разбора медленной операции
- Воспроизвести операцию и найти её в технологическом журнале по событию
DBMSSQLилиCALL. - Перевести имена таблиц (
_AccumRg…,_Fld…) в объекты 1С через структуру хранения. - Посмотреть план: сканирование большой таблицы, ошибка оценки строк, отсутствующий индекс.
- Если время уходит на ожидание, а не на выполнение — искать блокирующий сеанс.
- Править запрос или индекс в конфигурации, а не только железо.