В процессе администрирования и оптимизации крупных информационных систем на платформе 1С:Предприятие специалисты часто сталкиваются с проблемами производительности, вызванными блокировками. Основным инструментом для их расследования является технологический журнал (ТЖ) 1С. Однако при его базовой настройке легко совершить ошибки: либо перегрузить дисковую подсистему избыточным логированием, либо упустить критически важные данные.
В этой статье мы подробно разберем, как правильно составить конфигурационный файл технологического журнала, проанализируем поведение системы при различных типах таймаутов, выясним причину отсутствия событий TTIMEOUT при блокировках СУБД и соберем оптимальный «джентльменский набор» настроек для постоянного использования на рабочем сервере.
---
Рассмотрим ситуацию, с которой часто сталкиваются администраторы 1С (описанную в сообщении 10 форума): при возникновении ошибки превышения времени ожидания блокировки в технологическом журнале фиксируется только событие EXCP с текстом:
«Конфликт блокировок при выполнении транзакции: Microsoft SQL Server Native Client: Превышено время ожидания запроса на блокировку... native=1222»
При этом специализированные события TTIMEOUT, настроенные для отслеживания таймаутов, в логах полностью отсутствуют. Чтобы понять, почему так происходит, проанализируем разницу между двумя принципиально разными механизмами блокировок в 1С:
rphost) отправляет SQL-запрос к базе данных, СУБД пытается наложить собственные блокировки на таблицы или строки СУБД. Если СУБД обнаруживает конфликт (например, другая транзакция изменяет те же строки), она приостанавливает выполнение SQL-запроса от 1С.
Для платформы 1С в этот момент процесс просто находится в ожидании ответа по сети от СУБД. Платформа не «знает», что внутри MS SQL Server происходит конфликт блокировок. Когда на уровне СУБД истекает таймаут ожидания блокировки (в 1С для MS SQL Server при подключении устанавливается таймаут в 20 секунд), СУБД возвращает клиенту критическую ошибку с кодом native=1222. Платформа воспринимает это как стандартный сбой СУБД и генерирует исключение EXCP. Событие TTIMEOUT при этом не регистрируется, так как менеджер управляемых блокировок 1С не контролировал этот процесс.
Таким образом, для расследования блокировок на уровне СУБД стандартных настроек ТЖ, ориентированных только на управляемые блокировки, недостаточно. Требуется настроить сбор событий СУБД и правильно связать их с контекстом исполнения кода 1С.
---
Рассмотрим популярные варианты настроек ТЖ, которые часто используются администраторами, и разберем их слабые и сильные стороны.
В первом сообщении темы представлен шаблон, ориентированный на раздельный сбор логов:
<?xml version="1.0" encoding="UTF-8"?>
<ns:config xmlns:ns="http://v8.1c.ru/v8/tech-log">
<ns:log history="48" location="D:\1C_log\Base1C\SQLlocks">
<ns:event>
<ns:eq property="Name" value="DBMSSQL"/>
<ns:eq property="p:processName" value="Base1C"/>
<ns:eq property="lkp" value="1"/>
</ns:event>
<ns:property name="p:processName"/>
<ns:property name="Context"/>
<ns:property name="Sql"/>
<ns:property name="lkp"/>
<!-- Остальные свойства -->
</ns:log>
</ns:config>
Анализ настройки: Это грамотный подход для отслеживания проблем на стороне СУБД. Свойство lkp (Lock Postponed) принимает значение 1, когда SQL-запрос не может быть выполнен немедленно и встает в очередь ожидания блокировки на уровне СУБД. Фильтрация по этому свойству позволяет отсечь миллиарды быстрых и успешных запросов, записывая в ТЖ только те обращения к СУБД, которые реально испытывали проблемы с параллельным доступом.
Минус: Использование пространства имен ns: в тегах XML может приводить к сбоям чтения конфигурации на некоторых релизах платформы. Рекомендуется использовать стандартный синтаксис без префиксов.
Часто в статьях встречается рекомендация собирать события TLOCK следующим образом:
<event>
<eq property="Name" value="TLOCK"/>
</event>
<property name="all"/>
Критика настройки: Сбор события TLOCK в чистом виде без дополнительных фильтров на продуктивной базе с активной работой пользователей гарантированно приведет к деградации производительности сервера. Событие TLOCK регистрирует каждую установку управляемой блокировки, даже если она прошла мгновенно за микросекунду. За несколько часов работы лог разрастется до сотен гигабайт, забив дисковую систему операциями записи.
В сообщении 4 предлагается радикальный шаблон:
<log history="72" location="C:\Program Files\1cv8\log">
<event>
<ne property="Name" value=""/>
</event>
<property name="all"/>
</log>
Критика настройки: Этот шаблон собирает абсолютно все события технологического журнала. Как справедливо отмечает автор сообщения, включать такую настройку на продуктивном сервере можно не более чем на 3-5 минут для локального выявления плавающей проблемы. Постоянная работа ТЖ в таком режиме вызовет полный отказ дисковой подсистемы сервера приложений 1С.
---
Для того чтобы иметь возможность расследовать как управляемые блокировки, так и блокировки СУБД, не снижая производительность сервера и экономя место на жестком диске, мы рекомендуем использовать оптимизированный шаблон logcfg.xml. Рассмотрим его структуру:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
<!-- Основной лог для сбора критических ошибок и блокировок -->
<log history="48" location="D:\1C_log\LocksAndExceptions">
<!-- Фиксируем все исключения (включая ошибки СУБД native=1222) -->
<event>
<eq property="Name" value="EXCP"/>
</event>
<!-- Фиксируем таймауты и взаимоблокировки управляемых блокировок -->
<event>
<eq property="Name" value="TTIMEOUT"/>
</event>
<event>
<eq property="Name" value="TDEADLOCK"/>
</event>
<!-- Фиксируем только те управляемые блокировки, которые вызвали реальное ожидание -->
<event>
<eq property="Name" value="TLOCK"/>
<ne property="WaitConnections" value=""/>
</event>
<!-- Фиксируем запросы к СУБД, которые встали в очередь ожидания блокировки -->
<event>
<eq property="Name" value="DBMSSQL"/>
<eq property="lkp" value="1"/>
</event>
<!-- Дополнительно: фиксируем аномально долгие SQL-запросы (дольше 15 секунд) -->
<event>
<eq property="Name" value="DBMSSQL"/>
<gt property="Duration" value="15000000"/>
</event>
<!-- Выгружаем все доступные свойства для отслеживаемых событий -->
<property name="all"/>
</log>
<!-- Сбор дампов при аварийном завершении рабочих процессов rphost -->
<dump create="true" location="D:\1C_log\dumps" type="3" />
</config>
Преимущества данного шаблона:
TLOCK по условию <ne property="WaitConnections" value=""/> позволяет записывать только те управляемые блокировки, при попытке установки которых сеанс был вынужден ожидать завершения других транзакций. Это сокращает объем логов в сотни раз.lkp="1" для DBMSSQL обеспечивает сбор информации о заблокированных запросах к СУБД.history="48"), что гарантирует защиту диска от переполнения.---
Проанализируем ситуацию, когда на сервере произошел сбой из-за конфликта блокировок СУБД, и выясним причину с помощью собранных логов ТЖ:
EXCP, содержащее текст native=1222 или фразу Превышено время ожидания запроса на блокировку. Из этого события мы получаем:
t:connectID).p:processName) и контекст выполнения (Context), указывающий на конкретную строку модуля 1С, на которой произошел сбой.t:connectID переходим к анализу событий DBMSSQL с признаком lkp=1, произошедших незадолго до падения транзакции. Здесь мы увидим фактический SQL-текст запроса (свойство Sql), который СУБД не смогла выполнить вовремя.
logcfg.xml специализированный корневой тег:
<dbmslocks/>
Важно: Начиная с версии платформы 8.3.8, при наличии этого тега платформа 1С автоматически опрашивает системные таблицы MS SQL Server при возникновении ожиданий на уровне базы данных. В ТЖ запишется подробная информация о блокирующем и заблокированном соединениях СУБД. Включайте данный тег исключительно на период расследования, так как он создает дополнительную нагрузку на СУБД.
---
Многие разработчики ошибочно полагают, что перевод конфигурации на «Управляемый режим блокировок» полностью исключает появление конфликтов на уровне СУБД. Выясним основные причины, почему транзакционные блокировки MS SQL Server продолжают возникать и приводить к ошибкам native=1222:
Рассмотрим ситуацию: при записи документа или выполнении запроса СУБД должна прочитать или обновить определенные строки таблицы. Если для используемых в условии ГДЕ полей отсутствует индекс, СУБД не может быстро найти нужные записи. Вместо этого MS SQL Server выполняет операцию Table Scan (сканирование всей таблицы) или Index Scan (сканирование всего индекса).
Чтобы гарантировать целостность данных во время сканирования всей таблицы, СУБД накладывает блокировку на всю таблицу целиком, а не на конкретные строки. В этот момент любая другая транзакция, пытающаяся записать данные в эту таблицу, встает в очередь ожидания и в итоге падает по таймауту.
СУБД расходует оперативную память на поддержание каждой блокировки строки. Если транзакция изменяет или считывает очень большой объем данных (порог в MS SQL Server обычно составляет более 5000 блокировок строк на одну таблицу), СУБД в целях оптимизации ресурсов выполняет эскалацию блокировок — заменяет множество мелких блокировок строк одной монопольной блокировкой всей таблицы (Table Lock). Все параллельные транзакции к этой таблице мгновенно блокируются.
Для корректной параллельной работы управляемых блокировок 1С на СУБД MS SQL Server критически важно активировать параметр базы данных Read Committed Snapshot Isolation (RCSI). Разберем по шагам, как проверить и включить данный режим:
ALTER DATABASE [Имя_Вашей_Базы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [Имя_Вашей_Базы] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [Имя_Вашей_Базы] SET MULTI_USER;
Если режим RCSI отключен, любые операции чтения (даже обычные отчеты) будут накладывать разделяемые блокировки (S-блокировки) на таблицы СУБД, которые будут конфликтовать с транзакциями записи, вызывая массовые ожидания и таймауты.
Если в конфигурации у части объектов метаданных свойство «Режим управления блокировкой данных» установлено в значение «Автоматический», а у других — в «Управляемый», платформа будет использовать смешанный режим. В автоматическом режиме СУБД накладывает избыточные жесткие транзакционные блокировки, которые будут конфликтовать с транзакциями управляемого режима, сводя на нет всю оптимизацию.
---
Мы проанализировали особенности настройки технологического журнала 1С для выявления причин блокировок. Понимание разницы между управляемыми блокировками и механизмами СУБД позволяет администратору быстро локализовать источник проблемы, не тратя время на поиск несуществующих событий TTIMEOUT при системных сбоях базы данных. Используйте предложенный «джентльменский набор» настроек ТЖ для постоянного мониторинга ваших баз данных, своевременно проводите аудит индексов и следите за настройками СУБД.