Частые вопросы по производительности «1С:Документооборота»
Приведем ответы на частые вопросы, связанные с производительностью «1С:Документооборота».
Вопрос 1
Есть ли в «1С:Документообороте» оценка производительности?
В «1С:Документообороте» версии КОРП и ДГУ есть встроенная оценка производительности. Рекомендуется включить ее перед началом работы пользователей в программе: Настройка и администрирование — Настройка программы — Общие настройки — Выполнять замеры производительности.
После этого программа автоматически будет замерять время выполнения ключевых операций: создание документа, запуск процесса, открытие и создание файла, выполнение задачи и другие. Эталонное время ключевых операций приведено здесь. На основе полученных данных удобно вовремя обнаружить снижение производительности программы и провести первичный анализ.
Чтобы увидеть средние показатели за определенный период, выполните команду Время выполнения ключевых операций в меню раздела Настройка и администрирование.
Анализ и контроль производительности можно также вести по методике APDEX — команда Оценка производительности в меню раздела Настройка и администрирование.
Вопрос 2
С чего начать проверку при замедлении работы программы?
При замедлении работы программы рекомендуется проверить формат журнала регистрации. Также эту проверку рекомендуется проводить после обновления платформы «1С:Предприятия» на версию 8.3.7 или после создания информационной базы с нуля.
Вопрос 3
Что делать, если у рядовых пользователей ключевые операции выполняются более 15 секунд? По прошествии этого времени операции выполняются без ошибок. При входе в программу под Администратором задержек нет. Все рекомендованные настройки СУБД и сервера «1С:Предприятие» выполнены.
Во-первых, проверьте версию конфигурации. Если установлена версия 1.4.xx, необходимо перейти на версию 2.0, куда включено много доработок по быстродействию.
Если проблема воспроизводится не в 100% случаев:
Вопрос 4
Что делать, если зафиксированы периодические замедления работы, например, раз в минуту?
Проверьте версию конфигурации. Если это версия 2.0.9 — 2.0.13 включительно, то обновитесь на более свежую или отключите автоматическую проверку контрагентов по ЕГРН (Настройка и администрирование — Настройки программы — Контрагенты — Автоматически проверять контрагентов по ЕГРН).
Вопрос 5
Что делать, если операция длится более 20 секунд, после чего выдает ошибку «Превышено максимальное время ожидания предоставления блокировки»? Как правило, ошибка проявляется у всех пользователей.
Анализ проблем производительности по динамике мониторинга RAS 1C
Мы опишем результаты наблюдений и выводы по состоянию производительности системы через мониторинг RAS 1C основанный на наших наблюдениях и мнении/советах коллег по цеху. Наиболее показательны изменения для больших баз по количеству работающих пользователей на одном кластере. Иначе требуется проводить агрегирование показателей таких как очередь какого-нибудь свойства, если на сервере много кластеров или на реальном много виртуальных машин для общей оценки сервера.
Также на поведение параметров контролируемой целевой базы 1С будет оказывать влияние версия платформы, окружение, конфигурация и это также нужно будет учесть при сравнении. Однако, динамика и характер поведения должны быть похожи. Мы выполняли анализ на версиях 8.3.14, 8.3.15, 8.3.16 и конфигурации ERP 2.4.
I) Свойства процессов
Номер строки (по порядку)
Содержит объем виртуальной памяти, занимаемой рабочим процессом, в килобай тах.
Средняя за последние 5 минут доступная производительность. Определяется по времени реакции рабочего процесса на эталонный запрос. В соответствии с доступной производительностью кластер серверов принимает решение о распределении клиентов между рабочими процессами.
Количество соединений рабочего процесса с пользовательскими приложениями.
Показывает среднее время обслуживания рабочим процессом одного клиентского обращения. Оно складывается из: значений свойств AvgServerCallTime, AvgDBCallTime, AvgLockCallTime, AvgBackCallTime.
Параметр состояния процессов avg-call-time
Параметр avg-call-time – позволяет увидеть проблемы загрузки хоста, если один из них находится под нагрузкой
Вот так выглядит график средней нагрузки
В этот момент было запущено тяжелое задание по пересчету регистра. Всем тем, кто-попадал на этот процесс было «плохо».
Если же все процессы показывают рост нагрузки, то скорее всего проблема возникла у менеджера, и он перестал корректно разруливать ситуацию.
Можно поставить оповещение о изменении данной ситуации, нормальное среднее значение должно быть значительно менее 1. При значениях от 1 до 2-3 возможны проблемы. При значениях более 7-10 можно считать, что мы потеряли пациента.
Во всех случаях серьезных проблем с хостами рекомендуем выполнить мягкий перезапуск.
Вот так выглядит показатель среднее avg-call-time при проблемах на сервере.
Вот так выглядит нагрузка на процессор в этот момент:
Количество процессов
Изменение количества процессов, также график позволяющий определить проблемы. Резкий рост или превышение некоторого установившегося количества, также является критерием того что у нас происходят какие-то проблемы.
Вот так меняется количество процессов при аварии:
Показатель расхода памяти
Показатели расхода памяти особенно проявляются с увеличением количества процессов. Рост памяти выше доступных в системе приведет к остановке служб. На графике ниже можно проследить рост потребления после запуска нового процесса.
Показатель производительность
Вот так выглядит падение производительности по показателю доступная производительность:
II) Свойства соединений
Содержит номер соединения.
Номер строки (по порядку)
Показатель соединений session-number
Если следить за связью между процессами и сеансами пользователей, то можно легко определить нормальные и не нормальные показатели для состояния системы. Об использовании нейронных сетей для определения критичных аномалий, о которых рассказывал на конференции я буду рассказывать позже (сейчас есть решаемые технические проблемы, которые не позволяют их использовать массово без сторонних приложений и с функционалом из коробки – банально не хватает времени).
Как только количество соединений между процессами и сеансами в единицу времени превышает некоторый порог, то стоит трубить о проблемах. На рисунке ниже показана ситуация аварии, в момент пика службы 1С перестали обслуживать и произошел самостоятельный перезапуск всех процессов с дальнейшим падением менеджера кластера. Он настолько ушел в себя, что не отпустил кэш и пришлось его удалять вручную.
Для хорошо нагруженной системы обычно такой показатель колеблется в районе 30-40 соединений в единицу.
Вот так показатель количество строк при падении производительности с полным зависанием служб.
Рекомендуемые агрегируемые функции:
III) Свойства сеансов
Свойство
Синоним
Функция агрегации
Описание
Номер строки (по порядку)
время вызова (текущее)
Содержит интервал времени в миллисекундах, прошедший с момента начала обращения, в случае, если сеанс выполняет обращение к серверу 1С:Предприятия. Иначе – 0.
время вызова (текущее)
время вызова (текущее)
Е сли в момент получение списка соединений информационной базы методом GetInfoBaseConnections данное соединение выполняло обращение к серверу баз данных, то свойство содержит время в секундах, в течение которого выполняется данное обращение к серверу баз данных. В противном случае – 0.
процессорное время (текущее)
Процессорное время текущее
процессорное время (текущее)
Как уже ранее рассказывал, то стоит следить сразу несколькими параметрами
Свойство duration-current
Показатель duration-current (время вызова (текущее)) показывает обслуживание пользователя процессом. Если же количество пользователей со значением этого параметра (отличным от 0 в каждый момент времени) растет, то сервисы 1с не успевают обслуживать, кто-то запустил что-то тяжелое и в итоге может привести к серьезному снижению производительности. Обычно значения, превышающие 60 штук (зависит от конкретной обслуживаемой системы) повод задуматься о том, что начинаются проблемы.
Предполагаем в данном случае отследить пользователя по табличной части «Данные» смотри ниже. Далее связаться с ним и обсудить решение проблемы. Возможно приложение зависло и его достаточно удалить, и система придет в норму, или попросить пользователя не запускать тяжелых задач. А возможно проблема производительности какой-либо формы или обработки и требуется ее оптимизация и рефакторинг.
Рекомендуем использовать следующие агрегирующие функции:
Свойство db-proc-took
Показатель db-proc-took (захвачено СУБД) характеризует обращение процесса к СУБД. Если количество таких обращений растет в единицу времени, то это говорит о том, что СУБД не успевает обслуживать запросы 1С. Такое поведение может возникать во время блокировок – когда один пользователь захватил популярный регистр, а все другие начинают его ждать. Недостаточной производительности самого сервера СУБД. Наличия большого количества неоптимальных запросов. Наличия операций, которые не рекомендуется запускать в момент высокой нагрузки пользователей – удаление помеченных, пересчет регистров и т.п.
Разбор проблем можно выполнять в соответствии с рекомендациями выше. А также возможно проверить настройку и работу сервисных заданий на сервере СУБД – обновление статистики, или другие настройки.
Рекомендуем использовать следующие агрегирующие функции:
Показатель cpu-time-current
Данный показатель обычно необходимо смотреть с duration-current. Если он значительно большой, то это говорит о том, что пользователь действительно запустил что-то существенно сжигающее мощность сервера и стоит связаться с пользователем, ограничить или удалить соединение.
Совместный анализ и учет свойств duration-current и db-proc-took
Если захват и время текущее больше нормы, то видно, что пользователь нагрузил сервер. А чем нагрузил можно узнать из журнала действий пользователя по номеру сеанса или ТЖ (удалив сеанс пользователя мы сгенерируем ошибку).
На графике ниже видно, что выполняются ресурсоемкие операции (фоновые задания) с постобработкой данных на сервере 1С (захвачено СУБД менее времени вызова (текущее)). Показатели время вызова и потребления процессора высокие. Но пока не превышена критическая отметка и уровень тревоги «желтый»
Если же у вас среднее состояние каждый день показывает высокую нагрузку, то скорее всего следует обновить ваши ресурсные мощности.
Количество пользователей
Количество пользователей обычно гладкий и равномерный график без резких скачков. Следить необходимо за резким изменением его поведения или резкими изменениями изменения количества спящих пользователей. На рисунке ниже видна аномалия после аварии служб 1С, в результате были выбиты практически все пользователи.
IV) Настройка обработки ситуации по комбинации показателей
Таблица настройки для реакции по комбинациям показателей выглядит следующим образом:
Для понимания взаимоблокировок необходимо знать, что такое блокировка и ожидание на блокировке. Подробная информация по этой теме содержится в статье базы знаний “Блокировки данных в 1С:Предприятии 8”. Рекомендуется предварительно ознакомиться с этим материалом для лучшего понимания текста настоящей статьи.
В случае взаимоблокировки двух сессий конфликт заключается в том, что сессия 1 ожидает снятия блокировки, установленной сессией 2, в то время как сессия 2, в свою очередь, ожидает снятия блокировки, установленной сессией 1. Ни одна из сессий не может ни продолжить свою работу (из-за ожидания), ни снять свою блокировку для того, чтобы дать конкурирующей сессии продолжить работу.
Такой конфликт не может быть разрешен без участия внешних (по отношению к обеим сессиям) механизмов. Подобные механизмы реализованы во всех СУБД, используемых “1С:Предприятием”, а также в самом сервере “1С:Предприятия” (для обнаружения неразрешимых конфликтов управляемых блокировок). Будем называть эти механизмы “менеджерами взаимоблокировок”.
Менеджер взаимоблокировок работает следующим образом:
Следует учитывать, что во взаимоблокировках могут участвовать несколько (более двух) сессий “1С:Предприятия”. Причем одна и та же причина может приводить к возникновению разных (по конфигурации и по сложности) взаимоблокировок с различным количеством участников и блокировок между ними. Поэтому при анализе большого количества взаимоблокировок в системе всегда имеет смысл начинать с самых простых взаимоблокировок – с минимальным количеством участников и с самыми простыми схемами. Высока вероятность того, что, устранив одну простую взаимоблокировку вы одновременно устраните несколько других – в том числе более сложные.
Другой важной особенностью взаимоблокировок является тот факт, что взаимоблокировка почти всегда “распределена” по нескольким различным строкам кода конфигурации. При этом на начальном этапе анализа пользователю известна только одна строка кода. Это может быть, например, последняя строка, выполненная “жертвой” перед тем, как ее транзакция была отменена менеджером взаимоблокировок (эта строка доступна в информации об ошибке) или строка кода конфигурации, которую выдал ЦУП в дереве аналитической информации.
При этом причина взаимоблокировки (ошибка, приводящая к ее возникновению) может находиться совсем в другом месте исходного кода. Это создает определенные трудности при анализе и устранении взаимоблокировок.
Известны следующие типичные причины возникновения взаимоблокировок в системах на платформе “1С:Предприятие 8”:
В настоящей статье будут рассмотрены особенности возникновения этих видов взаимоблокировок, объяснены причины, по которым они возникают, и даны рекомендации по анализу и устранению этих причин.
Следует заметить, что взаимоблокировки не всегда поддаются анализу в том случае, если нам известна только одна строка кода – та, в которой было получено сообщение об ошибке взаимоблокировки. Как правило, для анализа взаимоблокировки необходимо использовать подробную информацию, предоставляемую “Центром управления производительностью”. Однако для понимания информации ЦУП необходимо знать основные схемы взаимоблокировок и причины, по которым они возникают. Поэтому рекомендуется сначала освоить материал следующих четырех разделов, а затем, если понадобится, переходить к анализу информации, предоставляемой ЦУП.
Текущая версия ЦУП показывает схемы взаимоблокировок только в том случае, если исследуемая информационная база работает с использованием MS SQL Server 2005.
Повышение уровня блокировки ресурса в рамках одной транзакции
Общие сведения
Повышение уровня блокировки в рамках одной транзакции является наиболее распространенной причиной возникновения взаимоблокировок.
Схема возникновения взаимоблокировки такова. Две конкурирующие транзакции (Т1 и Т2) читают один и тот же ресурс – Р1. При этом устанавливаются разделяемые блокировки на этот ресурс. Разделяемые блокировки от конкурирующих транзакций могут существовать одновременно, поэтому к моменту времени t1 обе транзакции успешно установили свои блокировки и продолжают работу.
Затем транзакция Т1 изменяет ресурс Р1 и пытается его записать. При этом устанавливается эксклюзивная блокировка на этот ресурс. Однако эта блокировка не может быть установлена одновременно с разделяемой блокировкой от транзакции Т2, поэтому она устанавливается в состояние ожидания. Транзакция Т1 прекращает работу и ждет, пока будет снята разделяемая блокировка, установленная транзакцией Т2.
Транзакция Т2, в свою очередь, хочет записать ресурс Р1, для чего также предпринимает попытку заблокировать его в эксклюзивном режиме. Однако это невозможно, так как существует уже установленная транзакцией Т1 разделяемая блокировка на этот ресурс. Транзакция Т2 также прекращает работу и ждет, пока будет снята разделяемая блокировка, установленная транзакцией Т1.
Обе транзакции находятся в режиме ожидания и не могут ни продолжить работу, ни освободить заблокированные ими ресурсы.
Причина возникновения взаимоблокировки данного вида – повышение уровня изоляции заблокированного ресурса в рамках одной транзакции. Транзакции сначала блокировали ресурс при помощи разделяемой блокировки, а затем повышали уровень блокировки до эксклюзивного.
Применительно к данному случаю перед чтением ресурса необходимо было заблокировать его в эксклюзивном режиме. Тогда картина изменилась бы следующим образом:
В данном случае обе транзакции, перед тем как читать ресурс Р1, устанавливают на него эксклюзивную блокировку. Одна из транзакций (Т1) успевает сделать это первой. К моменту времени t1 ресурс Р1 оказывается заблокированным в эксклюзивном режиме и транзакция Т2, которая не может установить свою блокировку, становится в ожидание на блокировке.
Особенности взаимоблокировок данного вида
Взаимоблокировки данного вида достаточно просты для анализа. При разработке (или доработке) системы следует всегда использовать сформулированное выше правило: блокировка в транзакции должна изначально осуществляться с максимально необходимым уровнем изоляции. Это позволит полностью исключить возникновение таких взаимоблокировок в системе.
Типичной ошибкой в коде конфигурации, которая может приводить к возникновению взаимоблокировок данного вида, является неблокирующее чтение и последующая запись в рамках одной транзакции:
Для возникновения взаимоблокировки данного вида необходимо одновременное выполнение следующих условий:
Автоматический режим. Чтение без опции “ДЛЯ ИЗМЕНЕНИЯ” и последующая запись в рамках одной транзакции
Рассмотрим следующий пример.
Обратите внимание на то, что проведение документа выполняется в неявной транзакции, которая автоматически открывается “1С:Предприятием”. Таким образом, весь текст обработчика проведения будет выполнен в рамках одной транзакции.
При выполнении запроса, описанного в данной функции, происходит чтение остатков регистра накопления “ТоварыНаСкладах”. При этом автоматически устанавливается разделяемая блокировка остатков списываемых товаров. Эта блокировка не позволит конкурирующей транзакции изменить остатки по данным товарам, но позволит ей считать остатки. То есть чтение является неблокирующим.
В этой функции выполняется запись регистра накопления “ТоварыНаСкладах”. В том случае, если остатки по товару реально изменились, при записи будет автоматически установлена эксклюзивная блокировка на остатки по данному товару. То есть произойдет повышение уровня изоляции ресурса в рамках одной транзакции.
Если несколько пользователей системы будут одновременно списывать одинаковые товары с одних и тех же складов, это может привести к возникновению взаимоблокировки.
Для того чтобы избежать возникновения взаимоблокировки, необходимо сделать чтение остатков блокирующим. Для этого используется опция “ДЛЯ ИЗМЕНЕНИЯ”.
Необходимо изменить функцию “ПроверитьОстатки” следующим образом:
Автоматический режим. Чтение в объектной технике и последующая запись
Предположим, что в коде конфигурации определена следующая процедура
В транзакции считывается элемент справочника “Контрагенты”. Чтение реализовано в объектной технике. При выполнении этой строки кода “1С:Предприятие” выполнит запрос к базе данных, который автоматически установит разделяемую блокировку для данного контрагента.
Затем в этой же транзакции реквизиты контрагента изменяются, и объект записывается в информационную базу. Перед записью будет автоматически установлена эксклюзивная блокировка для данного контрагента, то есть произойдет повышение уровня изоляции ресурса. В том случае если эта операция будет выполняться несколькими пользователями одновременно, возможно возникновение взаимоблокировок.
В этом случае процедура будет выглядеть следующим образом:
Управляемый режим. Чтение без установки блокировки (либо с установкой разделяемой блокировки) и последующая запись
Если в примере 1 перевести конфигурацию в управляемый режим блокировки данных в транзакции, то опция “ДЛЯ ИЗМЕНЕНИЯ” будет игнорирована “1С:Предприятием”, и необходимой эксклюзивной блокировки перед чтением остатков не произойдет. Кроме того, разделяемая блокировка, которая автоматически установится на уровне СУБД, будет снята после завершения выполнения запроса (то есть до конца транзакции). Такая ситуация может привести к нарушению бизнес-логики системы.
Обратите внимание на то, что взаимоблокировки в данном случае не произошло. Вместо этого была нарушена бизнес-логика системы (списаны товары, отсутствующие на складе), что по серьезности последствий намного хуже, чем взаимоблокировка.
Источником этой проблемы является низкий уровень изоляции транзакции на уровне СУБД. Разделяемые блокировки, которые были автоматически установлены в момент чтения остатков, снялись непосредственно после выполнения запроса и остались незащищенными (то есть незаблокированными) до конца транзакции. Отсюда следует необходимость установить такую блокировку, которая бы защищала итоги до окончания транзакции. Для решения таких задач предназначены явные управляемые блокировки, устанавливаемые из кода конфигурации.
Подробная информация о том, как работать с управляемыми блокировками, содержится в данной статье базы знаний.
Для данного примера измененный текст функции должен быть следующим:
Обратите внимание на то, что для блокировки выбран режим “Исключительный”. Это сделано в соответствии со сформулированным выше правилом: необходимо изначально устанавливать блокировку с наивысшим требуемым уровнем изоляции ресурсов.
Если в данном случае установить режим блокировки “Разделяемый”, то при одновременной работе нескольких пользователей возможно возникновение взаимоблокировки на уровне “1С:Предприятия”.
Захват ресурсов в разном порядке
Общие сведения
Захват ресурсов в разном порядке является второй наиболее распространенной причиной возникновения взаимоблокировок.
В отличие от взаимоблокировки, возникающей при повышении уровня изоляции ресурса в рамках одной транзакции, данная блокировка возникает не на одном ресурсе, а минимум на двух (или более).
Схема возникновения взаимоблокировки для двух ресурсов такова. В начале две конкурирующие транзакции (Т1 и Т2) захватывают два разных ресурса – Р1 и Р2. Устанавливаемые при этом блокировки не мешают друг другу (так как заблокированы разные ресурсы), поэтому к моменту времени t1 обе транзакции успешно блокируют ресурсы и продолжают работу.
Затем транзакция Т1 пытается заблокировать ресурс Р2. Однако это невозможно, поскольку он уже заблокирован транзакцией Т1. В свою очередь, транзакция Т2 пытается заблокировать ресурс Р2, но это также невозможно, поскольку он уже захвачен транзакцией Т1.
Возникает взаимоблокировка: обе транзакции находятся в режиме ожидания и не могут ни продолжить работу, ни освободить заблокированные ими ресурсы.
В данном примере все блокировки установлены в эксклюзивном режиме, однако это не является необходимым условием. Если бы первая пара блокировок была разделяемой, а вторая – эксклюзивной (или наоборот), то взаимоблокировка также возникла бы. Из-за этого взаимоблокировку из-за разного порядка захвата ресурсов иногда можно спутать со взаимоблокировкой из-за повышения уровня изоляции ресурса.
Также не имеет значения, какие именно действия транзакций привели к захвату ресурсов. Это могут быть операции чтения или записи ресурсов, а также установка управляемых блокировок в явном виде из кода конфигурации.
При блокировании ресурсов в одинаковом порядке картина изменится следующим образом:
В этом случае транзакция Т1 успевает первой заблокировать ресурс Р1. Транзакция Т2 пытается установить аналогичную блокировку, но не может этого сделать и становится в ожидание на блокировке.
Транзакция Т1 продолжает работу, выполняет все необходимые действия (при этом, в частности, захватывает ресурс Р2) и завершается. После завершения транзакции все установленные ей блокировки автоматически снимаются и транзакция Т2 продолжает работу. Ей также никто не мешает, и она успешно выполняет все необходимые действия, включая установку блокировок на ресурсы.
Особенности взаимоблокировок данного вида
Взаимоблокировки первого вида (возникающие по причине повышения уровня изоляции ресурса в транзакции) обычно проявляются при одновременной работе однотипных транзакций. Взаимоблокировки второго вида (возникающие из-за разного порядка захвата ресурсов в транзакции), как правило, проявляются при выполнении пользователями разных действий. Например, первый пользователь может вводить документ “РеализацияТоваров”, а второй – “ПоступлениеТоваров”.
Эта особенность делает взаимоблокировки данного вида неудобными для анализа на уровне кода. Если нам известна только строка кода, на которой жертва взаимоблокировки получила сообщение об ошибке, то мы не имеем следующей необходимой информации:
Как правило, для анализа взаимоблокировок данного вида необходимо использовать информацию, предоставляемую “Центром управления производительностью”.
Изначально разрабатывать приложение таким образом, чтобы в нем всегда использовался одинаковый порядок захвата ресурсов, – достаточно сложная организационная и техническая задача. Как правило, такие взаимоблокировки приходится анализировать и устранять по факту их возникновения во время многопользовательского нагрузочного тестирования либо при работе реальных пользователей системы.
Типичные причины возникновения взаимоблокировок данного вида таковы:
Захват ресурсов без учета порядка
При разработке кода конфигурации необходимо обеспечить правильную работу приложения в рамках одной транзакции. Это понятная и разрешимая задача. Однако взаимоблокировка данного вида возникает при конкурентной работе разных транзакций. Для того чтобы исключить потенциальную возможность таких взаимоблокировок, необходимо было бы анализировать код всех имеющихся в системе транзакций на предмет одинакового порядка захвата ресурсов. Для сложных конфигураций такая задача может оказаться невыполнимой.
Однако можно сформулировать несколько несложных правил, выполнение которых позволит значительно снизить риск возникновения взаимоблокировок данного вида:
Предположим, что в конфигурации определены два вида документов: “РеализацияТоваров” и “ПоступлениеТоваров”. Документы записывают движения в два регистра накопления: “ТоварыНаСкладах” и “ТоварыОрганизаций”. При этом движения заполняются и записываются в явном виде в обработчиках проведения документов.
При написании этого кода разработчики не учли порядок захвата ресурсов, в результате чего движения записываются в разном порядке. Например, в документе “РеализацияТоваровУслуг”:
Для того чтобы избежать этих взаимоблокировок, можно отказаться от записи движений в явном виде. В этом случае движения будут записываться платформой, которая будет делать это гарантированно в одинаковом порядке.
Другое решение – обеспечить одинаковый порядок записи движений организационными мерами. Например, подготовить проектный документ, который описывает рекомендуемый порядок захвата ресурсов и обеспечить выполнение этих рекомендаций всеми программистами системы.
Обратите внимание на то, что ресурсы захватываются (блокируются) не только при записи движений. Полный перечень операций, при которых происходит захват ресурсов:
Захват ресурсов в разном порядке в соответствии с требованиями алгоритмов обработки данных
Алгоритмы обработки информации могут требовать строго определенного порядка захвата ресурсов, и для разных алгоритмов этот порядок может быть различным. В этом случае задача может оказаться неразрешимой либо потребовать серьезного пересмотра структур данных и алгоритмов.
Возможна ситуация, при которой такой порядок записи движений, как в предыдущем примере, применен осознанно в связи с тем, что таков алгоритм обработки информации. Например, документ “РеализацияТоваров” должен сначала записать регистр “ТоварыНаСкладах”, затем при помощи запросов к этому и другим регистрам произвести некоторые вычисления и только потом – на основании результатов этих вычислений – сформировать и записать движения регистра “ТоварыОрганизаций”. В свою очередь, документ “ПоступлениеТоваров” может, наоборот, вычислять данные для регистра “ТоварыНаСкладах” на основании данных регистра “ТоварыОрганизаций”.
Например, при работе в автоматическом режиме мы можем выполнить запрос с опцией “ДЛЯ ИЗМЕНЕНИЯ” к виртуальной таблице остатков регистра “ТоварыОрганизаций” в обработчике проведения документа “РеализацияТоваров”. В качестве условия в этот запрос следует передать набор значений измерений, который будет изменяться в этой транзакции (то есть выборку из табличной части документа). В этом случае последовательность установки блокировок будет такая же, как в документе “ПоступлениеТоваров”: сначала будет блокироваться регистр “ТоварыОрганизаций”, а затем “ТоварыНаСкладах”. Взаимоблокировка при этом будет исключена.
При работе в управляемом режиме вместо запроса с опцией “ДЛЯ ИЗМЕНЕНИЯ” следует прописать в коде обработчика проведения явную блокировку пространства “РегистрНакопления.ТоварыОрганизаций” по соответствующему набору значений измерений.
Непредсказуемый порядок захвата ресурсов в СУБД при выполнении сложных запросов
При выполнении сложных запросов, включающих соединение нескольких таблиц, не всегда можно точно предсказать, в каком порядке эти таблицы будут обрабатываться СУБД. Этот порядок будет зависеть от выбора плана запроса, а план, в свою очередь, от множества непредсказуемых факторов – распределения данных по индексам, размеров таблиц, нагрузки на систему и т. д.
Иначе говоря, возможны такие ситуации, когда СУБД будет устанавливать блокировки при выполнении одного и того же запроса к нескольким ресурсам в разном порядке. При этом также возможно возникновение взаимоблокировок. Для устранения таких взаимоблокировок необходимо также установить искусственные блокировки на ресурсы в предопределенном порядке.
Неоптимальная работа запроса
При неоптимальной работе запроса блокируются избыточные ресурсы, что может значительно увеличить вероятность возникновения взаимоблокировок. Если взаимоблокировка возникла при выполнении прикладного запроса, следует провести анализ и оптимизацию его текста в соответствии с рекомендациями, данными в статье “Типичные причины неоптимальной работы запросов и методы оптимизации”.
Ошибка блокировок при работе внутренних механизмов MS SQL Server
Известны случаи возникновения взаимоблокировок при работе внутренних механизмов MS SQL Server. О возникновении таких взаимоблокировок говорят следующие сообщения об ошибках:
Обычно для возникновения взаимоблокировки необходимо участие четырех и более запросов (по два в двух конкурирующих транзакциях). Однако при выполнении некоторых запросов MS SQL Server может самостоятельно повышать уровень изоляции заблокированных ресурсов, что иногда также приводит к возникновению взаимоблокировки. В этом случае возможна взаимоблокировка, в которой участвуют всего два запроса от двух конкурирующих транзакций. Для возникновения такой взаимоблокировки необходимо одновременное выполнение следующих условий:
Соответственно, для устранения такой взаимоблокировки необходимо исключить любое из трех условий:
Анализ взаимоблокировок при помощи ЦУП
Как уже было отмечено выше, взаимоблокировки не всегда поддаются анализу на основании одной строки кода – той, в которой было получено сообщение об ошибке взаимоблокировки. Если исследуемая база работает с использованием MS SQL Server 2005, то есть возможность получить детальную информацию по взаимоблокировке с помощью Центра управления производительностью.
ЦУП пытается автоматически ранжировать взаимоблокировки по сложности, показывая на верхних позициях в списках более простые случаи. Однако оценить сложность взаимоблокировки возможно не всегда. Не стоит тратить много времени, пытаясь разобраться в сложной для понимания взаимоблокировке. Следует выбрать из списка более простой и понятный вам случай.
Для получения информации по взаимоблокировке необходимо выполнить следующую последовательность действий:
1. Настроить права доступа и подключиться к исследуемой информационной базе в режиме мониторинга (см. руководство по использованию ЦУП).
2. Добавить показатель “Анализ взаимоблокировок” в список показателей ЦУП.
3. Включить запись этого показателя.
Внимание! При включении записи аналитических показателей может наблюдаться падение производительности в исследуемой информационной базе.
4. Воспроизвести взаимоблокировку в исследуемой информационной базе либо дождаться, пока взаимоблокировка возникнет во время работы пользователей. О возникновении взаимоблокировки можно судить по значениям показателя “Количество взаимоблокировок”.
Внимание! После включения записи аналитического показателя ЦУП начинает сбор информации примерно через 1 минуту. Необходимо выдержать паузу между включением записи показателя и воспроизведением взаимоблокировки.
5. Выключить запись показателя “Анализ взаимоблокировок”. После выключения записи ЦУП начнет разбор и анализ собранной информации. Этот процесс может занять длительное время.
6. Остановить работу сценария “мониторинг” и подключиться к исследуемой базе в режиме просмотра. При необходимости выбрать интервал времени, на котором наблюдалась интересующая вас взаимоблокировка.
7. Нажать кнопку “Анализ”.
8. В форме анализа проблем производительности выбрать закладку “Код конфигурации”, раскрыть первую вершину дерева и двойным щелчком открыть форму анализа взаимоблокировок:
9. Будет открыта форма списка взаимоблокировок, в которых участвует выбранный источник проблем – строка кода конфигурации. Группы взаимоблокировок объединяют одинаковые (по схеме) взаимоблокировки, произошедшие в разное время. Поскольку в системе может наблюдаться множество различных взаимоблокировок, следует проанализировать каждую группу. Из группы следует выбирать наиболее простую взаимоблокировку.
Для того чтобы открыть взаимоблокировку в отдельном окне, следует дважды щелкнуть по ней мышкой.
10. Провести анализ схемы взаимоблокировки и причин ее возникновения.
Схема отображает все процессы, попавшие во взаимоблокировку, и полную хронологическую последовательность блокировок, установленных каждым процессом. При этом указываются не все блокировки, а только те, которые имеют (или могут иметь) отношение к данной взаимоблокировке. Для каждой блокировки указан контекст ее установки, то есть строка кода конфигурации, при выполнении которой она была установлена.
Далее приведены примеры анализа взаимоблокировок двух основных видов:
Примеры получены на измененной конфигурации УПП при помощи теста “Продажи” и доступны для самостоятельного изучения в демонстрационной базе ЦУП.
Повышение уровня блокировки ресурса в рамках одной транзакции
Рассмотрим пример взаимоблокировки, возникшей в результате повышения уровня блокировки ресурса в рамках одной транзакции:
Во взаимоблокировке участвуют два процесса (транзакции):
Для каждого процесса показана хронология событий, которая привела к возникновению взаимоблокировки.
Вначале оба процесса выполняют запросы, в результате которых успешно устанавливаются две блокировки:
Затем оба процесса пытаются выполнить два других запроса, но при установке блокировок возникает взаимное ожидание, то есть взаимоблокировка:
В этой взаимоблокировке можно видеть следующие характерные признаки взаимоблокировок данного вида (возникающих по причине повышения уровня блокировки ресурса):
1. Во взаимоблокировке участвует один ресурс – регистр накопления “ТоварыВРезервеНаСкладах”:
2. Процессы являются однотипными, то есть выполняются одинаковые прикладные действия и, соответственно, работает один и тот же код конфигурации:
Откроем конфигурацию исследуемой базы и проанализируем запрос, который исполняется в строке 506 модуля набора записей регистра накопления “ТоварыКПередачеСоСкладов”. При этом нас будет интересовать только обращение к заблокированному ресурсу – регистру “ТоварыВРезервеНаСкладах”.
Ниже приведен сокращенный текст процедуры КонтрольСвободныхОстатков_Реализация(), из которой вызывается интересующий нас запрос.
При выполнении данного запроса идет чтение остатков регистра ТоварыВРезервеНаСкладах. При этом будет установлена разделяемая блокировка, так как опция “ДЛЯ ИЗМЕНЕНИЯ” применена только к регистру “ТоварыКПередачеСоСкладов”.
Затем проанализируем код, который исполняется во второй интересующей нас строке: модуль набора записей регистра накопления “ТоварыВРезервеНаСкладах”, строка 395. Нас по-прежнему будут интересовать только обращения к регистру “ТоварыВРезервеНаСкладах”.
При выполнении этого запроса также производится чтение остатков регистра “ТоварыВРезервеНаСкладах”, но они читаются с опцией “ДЛЯ ИЗМЕНЕНИЯ”, то есть при этом будет установлена эксклюзивная блокировка.
Таким образом, регистр “ТоварыВРезервеНаСкладах” блокируется в рамках одной транзакции сначала разделяемой блокировкой, а затем эксклюзивной. Это и является причиной возникновения данной взаимоблокировки.
Для исправления этой ошибки необходимо изначально заблокировать остатки регистра “ТоварыВРезервеНаСкладах” с максимальным необходимым уровнем изоляции, то есть с опцией “ДЛЯ ИЗМЕНЕНИЯ”. При этом код процедуры изменится следующим образом:
Захват ресурсов в разном порядке
Рассмотрим пример взаимоблокировки, возникшей в результате захвата ресурсов в разном порядке:
В этой взаимоблокировке можно видеть следующие характерные признаки взаимоблокировок данного вида (возникающие по причине захвата ресурсов в разном порядке):
1. Во взаимоблокировке участвуют несколько (в данном случае два) ресурсов. При этом они захватываются в разном порядке.
2. Процессы являются разнотипными, то есть выполняются разные прикладные действия и, соответственно, разный код конфигурации.
Рассмотрим действия, которые выполняют эти два процесса, и блокировки, которые при этом устанавливаются.
1. Действия и блокировки процесса 1:
1.1. Процесс 1 выполняет запрос контроля остатков в строке 506 модуля набора записей регистра накопления “ТоварыКПередачеСоСкладов”. Рассмотрим фрагменты кода процедуры “КонтрольСвободныхОстатков_Реализация”, обращая внимание только на обращения к таблице “ТоварыНаСкладах.Остатки”.
В результате выполнения этого запроса успешно устанавливается разделяемая блокировка на остатки регистра “ТоварыНаСкладах”.
При двойном клике на первой блокировке процесса 1 откроется форма подробной информации о блокировке. Эта форма, в частности, содержит ссылку на выполнение интересующего нас запроса:
Открыв форму выполнения запроса, мы увидим полный стек вызовов кода конфигурации. Из этого стека становится понятно что интересующий нас запрос выполнялся при проведении документа “РеализацияТоваровУслуг” (в коде тестовой обработки соответствующая переменная имеет имя “Реализация”).
1.2. Следующее действие, выполненное процессом 1, имеет этот же стек вызова, но он заканчивается на строке “Реализация.Записать”.
Это означает, что оба действия были выполнены в результате проведения одного документа “РеализацияТоваровУслуг”, но первое действие было вызвано в явном виде из кода конфигурации, а второе – выполнено автоматически платформой.
Посмотрим, какой SQL-запрос был сгенерирован платформой при выполнении этого действия.
Это обновление таблицы остатков регистра накопления “ТоварыКПередачеОрганизаций”. При выполнении этого действия была установлена эксклюзивная блокировка на таблицу остатков этого регистра. Однако эта блокировка находится в режиме ожидания, так как имеется несовместимая с ней блокировка процесса 2.
2. Действия и блокировки процесса 2:
Процесс 2 выполняет одно-единственное действие – запись и проведение документа “РасходныйОрдер”. Оба действия, имеющие отношение к взаимоблокировке, выполняются платформой автоматически при проведении документа.
2.1. Первое действие: обновление остатков регистра накопления “ТоварыКПередачеОрганизаций”:
В результате этого действия устанавливается эксклюзивная блокировка на соответствующие остатки регистра “ТоварыКПередачеОрганизаций”. Именно эта блокировка мешает процессу 1 установить аналогичную блокировку при выполнении действия 1.2.
2.2. Второе действие: обновление остатков регистра накопления “ТоварыНаСкладах”:
В результате этого действия устанавливается эксклюзивная блокировка на соответствующие остатки регистра “ТоварыНаСкладах”. Однако в системе уже имеется несовместимая блокировка на эти же записи регистра, которая была установлена процессом 1 при выполнении действия 1.1. По этой причине блокировка процесса 2 устанавливается в режиме ожидания.
Итак, процесс 1 ожидает окончания транзакции процесса 2, в то время как процесс 2 ожидает окончания транзакции процесса 1. Получаем взаимоблокировку по причине захвата ресурсов в разном порядке. Процесс 1 захватил сначала регистр накопления “ТоварыНаСкладах”, а затем регистр “ТоварыКПередачеОрганизаций”. Процесс 2 захватил эти же регистры, но в обратном порядке.
Все запросы, попавшие во взаимоблокировку, выполняются при автоматической записи движений по регистрам при проведении документа. Проблема в том, что в документе “РеализацияТоваровУслуг” при записи движений в регистр “ТоварыКПередачеСоСкладов” захватывается таблица остатков регистра “ТоварыНаСкладах”. Именно это является причиной взаимоблокировки, однако обойтись без чтения этой таблицы, очевидно, нельзя, поскольку это часть алгоритма обработки данных.
Можно было бы попробовать изменить порядок записи движений в документе “РасходныйОрдер”, прописав в обработчике проведения этого документа следующий код:
Таким образом мы избавились бы от рассматриваемой взаимоблокировки, но создали бы опасность возникновения других взаимоблокировок. Для полной уверенности в их отсутствии нам пришлось бы проанализировать весь код конфигурации в поисках транзакций, которые записывают движения по этим двум регистрам, и везде произвести запись в явном виде и в нужном порядке. Кроме того, пришлось бы принимать организационные меры для того, чтобы разработчики впредь всегда записывали движения по этим регистрам только в явном виде и только в заданном порядке.
Поэтому в данном случае рекомендуется другой способ устранения взаимоблокировки – установка искусственной блокировки. Поскольку процесс 2 (проведение документа “РасходныйОрдер”) выполняет захват ресурсов автоматически, будем считать именно этот порядок правильным. Процесс 1 (“РеализацияТоваровУслуг”) захватывает ресурсы в неправильном порядке – сначала блокируется регистр “ТоварыНаСкладах”, затем – “ТоварыКПередачеОрганизаций”. Именно этот порядок должен быть изменен.
Для этого следует выполнить запрос с опцией “ДЛЯ ИЗМЕНЕНИЯ” к таблице остатков регистра “ТоварыКПередачеОрганизаций”. Этот запрос должен быть выполнен перед запросом в строке 506 модуля набора записей регистра “ТоварыКПередачеСоСкладов”. Условия запроса должны быть такими, чтобы считать (и, соответственно, заблокировать) все остатки, которые будут изменены при записи набора записей в действии 1.2.
Существует еще один вариант устранения этой взаимоблокировки. Блокировки, устанавливаемые процессом 1 (документ “РеализаяТоваровУслуг”), возникают только при работе в автоматическом режиме. Характерным признаком таких блокировок является значение поля режим = “Range…”:
Эти блокировки полностью исчезают при переходе в управляемый режим блокировки данных в транзакции. То есть данная взаимоблокировка будет невозможна при работе в управляемом режиме.