Как решить проблему внезапных дедлоков (взаимоблокировок) в 1С на MS SQL Server?

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

Каждый администратор баз данных и разработчик 1С рано или поздно сталкивается со страшным сном: в стабильно работающей системе внезапно начинаются массовые взаимоблокировки (дедлоки). Пользователи жалуются, что база «зависает», документы не проводятся, кассы на точках не могут пробить чеки, а обычный подбор номенклатуры в документ вызывает ошибку блокировки. Ситуация становится критической, когда документы записываются частично (например, из 128 строк записываются только 56, а остальные пропадают), а штатная выгрузка базы в формат .dt начинает завершаться с ошибками.

В этой статье мы подробно разберем, почему возникают такие проблемы, как на это влияют обновления законодательства (такие как переход на НДС 20% и ФФД 1.05), почему обычная выгрузка и загрузка базы через .dt временно решает проблему и как настроить MS SQL Server и конфигурацию 1С раз и навсегда, чтобы забыть о дедлоках.

Выясняем причину: почему выгрузка/загрузка базы через .dt временно решает проблему?

Автор темы отметил, что после выполнения выгрузки информационной базы в файл .dt и последующей загрузки ее в новую базу данных на SQL-сервере скорость работы выросла в 10 раз, а дедлоки мгновенно прекратились. Давайте проанализируем, что именно происходит на физическом уровне в СУБД во время этой операции:

  1. Полное пересоздание таблиц и индексов. Когда платформа 1С загружает данные из файла .dt, она не просто вставляет строки в существующие таблицы. Она полностью удаляет старую структуру базы данных на SQL-сервере и создает таблицы и индексы с нуля. В этот момент фрагментация абсолютно всех индексов становится равной 0%. Чтение данных начинает происходить максимально быстро, без лишних сканирований диска.
  2. Обновление статистики оптимизатора СУБД. При создании новых индексов MS SQL Server автоматически рассчитывает статистику распределения данных со 100% точностью (Full Scan). На основе свежей статистики оптимизатор СУБД строит идеальные планы запросов, мгновенно находя нужные строки. Если статистика устаревает, СУБД начинает «глупеть» и вместо быстрого поиска по индексу запускает сканирование всей таблицы.
  3. Пересчет итогов регистров. В процессе загрузки платформа заново рассчитывает таблицы итогов всех регистров накопления и бухгалтерии. Если в итогах были логические расхождения или «зависшие» копейки, они устраняются. Это исключает избыточные блокировки при проведении документов задним числом.
  4. Сжатие базы данных и очистка мусора. Из базы удаляются все неиспользуемые страницы и временные объекты, которые могли остаться после некорректного завершения транзакций.

Важное предупреждение: Фирма «1С» настоятельно рекомендует не использовать формат .dt как средство резервного копирования для баз на SQL. Если в вашей базе есть физические повреждения (например, поврежденные страницы на диске), выгрузка в .dt может пройти успешно, но загрузить базу обратно вы уже не сможете! Единственным надежным способом бэкапа для SQL-баз является создание файлов резервных копий средствами самой СУБД (файлы .bak).

Как «сломанные» индексы и устаревшая статистика порождают дедлоки

Давайте разберем по шагам механизм, связывающий плохую производительность дисков или фрагментацию индексов с возникновением взаимоблокировок:

Когда индекс сильно фрагментирован или статистика устарела, SQL-сервер не может быстро найти конкретную строку (например, остаток товара «Номенклатура А» на складе «Основной»). Вместо точечного поиска (Index Seek) СУБД вынуждена выполнять полное сканирование таблицы или индекса (Clustered Index Scan). Это приводит к двум катастрофическим последствиям:

Влияние обновлений законодательства (НДС 20% и ФФД 1.05) на блокировки

Почему дедлоки часто начинаются «ни с того ни с сего» после обновления конфигурации (например, УТ 10.3 под новые кассовые требования)? Выясним причину этой взаимосвязи:

При переходе на формат фискальных данных ФФД 1.05 система обязана передавать на кассовый аппарат детальные признаки расчета, ставку НДС и систему налогообложения для каждой строки чека. Разработчики часто реализуют это путем динамического обращения к справочнику номенклатуры и регистрам сведений в момент пробития чека.

Самая большая ошибка здесь — выполнение физической печати чека на ККТ внутри транзакции СУБД. Физический принтер чеков печатает медленно, обменивается данными с ОФД через интернет, и этот процесс может занимать от 2 до 10 секунд. Если все это время транзакция в 1С остается открытой, наложенные СУБД блокировки на таблицы товаров, остатков и касс продолжают удерживаться. Другие кассы выстраиваются в очередь ожидания и в итоге «отваливаются» по таймауту или вызывают взаимоблокировки.

Решение: Физическая фискализация (печать чека на кассе) должна быть полностью отделена от транзакции проведения документа в базе данных. Сначала документ должен быстро провестись в базе (это занимает миллисекунды), транзакция должна закрыться, и только после этого команда на печать чека должна отправляться на кассовый аппарат.

Пошаговое руководство по устранению дедлоков на MS SQL Server

Для того чтобы решить проблему дедлоков раз и навсегда, выполним комплексную настройку нашей СУБД и базы данных 1С.

Шаг 1. Настройка параметра MAXDOP на SQL-сервере

Параметр MAXDOP (Max Degree of Parallelism) определяет максимальное количество ядер процессора, которое СУБД может задействовать для выполнения одного запроса. По умолчанию этот параметр равен 0 (использовать все доступные ядра). Для баз данных 1С это крайне опасно, так как тяжелые запросы начинают параллелиться, вызывают взаимные блокировки потоков одного запроса (intra-query deadlocks) и перегружают процессор.

Установим значение MAXDOP в 1. Это принудительно заставит СУБД выполнять каждый отдельный запрос в один поток, что полностью ликвидирует внутризапросные дедлоки.

Для этого в среде SQL Server Management Studio (SSMS) выполним следующий скрипт:


EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'max degree of parallelism', 1;
RECONFIGURE;

Если у вас очень мощный сервер и многоядерные процессоры, можно установить значение от 2 до 4, но при этом обязательно нужно поднять порог стоимости параллелизма (cost threshold for parallelism) со стандартных 5 до 50 или 80 секунд, чтобы мелкие запросы касс гарантированно выполнялись в один поток.

Шаг 2. Включение версионирования строк (RCSI) в MS SQL

По умолчанию в базах 1С с автоматическим режимом блокировок читающие транзакции блокируют пишущие, а пишущие — читающие. Чтобы решить эту проблему на уровне СУБД, включим режим версионирования строк Read Committed Snapshot Isolation (RCSI). При этом читающие запросы будут получать согласованные версии строк из базы данных tempdb без наложения разделяемых блокировок (S-locks). Чтение больше никогда не будет блокировать запись!

Выполним по шагам скрипт для включения RCSI (обратите внимание, что базу потребуется перевести в монопольный режим, поэтому выполнять это нужно во время отсутствия пользователей):


-- Переводим базу в монопольный режим и сбрасываем активные соединения
ALTER DATABASE [Имя_Вашей_Базы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

-- Включаем режим версионирования строк
ALTER DATABASE [Имя_Вашей_Базы] SET READ_COMMITTED_SNAPSHOT ON;

-- Возвращаем базу в многопользовательский режим
ALTER DATABASE [Имя_Вашей_Базы] SET MULTI_USER;

Важное требование: Так как версии строк будут сохраняться во временной базе данных tempdb, нагрузка на дисковую систему, где лежит tempdb, существенно возрастет. Настоятельно рекомендуется перенести файлы базы tempdb на максимально быстрый физический диск (желательно NVMe SSD).

Шаг 3. Очистка процедурного кэша и проверка целостности базы данных

Если в базе данных возникли логические или физические сбои, их необходимо локализовать и устранить. Запустим проверку целостности базы данных без остановки работы пользователей (хотя это может вызвать временное снижение производительности):

DBCC CHECKDB ('Имя_Вашей_Базы') WITH NO_INFOMSGS, ALL_ERRORMSGS;

Если проверка выявила ошибки, базу необходимо перевести в монопольный режим и восстановить с помощью команды REPAIR_ALLOW_DATA_LOSS или восстановить из последнего чистого SQL-бэкапа.

Также сбросим старый кэш планов запросов, в котором могли зависнуть неоптимальные планы:

DBCC FREEPROCCACHE;

Шаг 4. Настройка регламентного обслуживания в MS SQL Server

Чтобы проблема с фрагментацией индексов и устаревшей статистикой не повторилась через несколько недель, настроим автоматические задачи обслуживания в SQL Server Agent:

  1. Дефрагментация индексов (Rebuild / Reorganize): Настройте ежедневную реорганизацию индексов, если фрагментация составляет от 10% до 30%, и полное перестроение (Rebuild) индексов, если фрагментация превышает 30%. Ребилд индексов полностью пересоздает их структуру.
  2. Обновление статистики (Update Statistics): Настройте ежедневное обновление статистики с включенной опцией FULLSCAN. Свежая статистика — это гарантия того, что SQL Server всегда будет выбирать оптимальные и быстрые планы запросов.
  3. Очистка процедурного кэша после обновления статистики: После массового обновления статистики рекомендуется выполнять очистку кэша планов запросов, чтобы СУБД гарантированно построила новые планы на основе актуальных данных.

Шаг 5. Постепенный переход на управляемый режим блокировок в 1С

Если ваша конфигурация (например, УТ 10.3) работает полностью в режиме автоматических блокировок, это накладывает серьезные ограничения на параллельную работу. Самым надежным архитектурным решением проблемы блокировок является перевод конфигурации (или ее наиболее критичных документов и регистров — «Чек ККМ», «Расходный ордер», регистры остатков товаров) на управляемый режим блокировок.

В управляемом режиме разработчик с помощью специального объекта БлокировкаДанных сам явно указывает платформе, какие конкретно записи и по каким разрезам (например, только по конкретному складу и списку товаров из документа) нужно заблокировать на время транзакции проведения. Это полностью исключает избыточные блокировки соседних данных и делает работу сотен пользователей легкой и бесконфликтной.

← На главную