Методика расследования ошибок блокировок
Если вы видите колебание время выполнения операций, но до ошибок блокировок дело пока (или чаще всего) не доходит, необходимо убедиться, что дело касается очереди в результате ожидания на транзакционных блокировках.
Стоит учитывать, что колебания производительности должны быть воспроизводимы. Правильно сравнивать скорость выполнения одной и той же операции, убедившись, что
- состав выполняемых действий одинаковый;
- данные, обрабатываемые в операциях, одинаковые или аналогичные настолько, что влияние их отличия может быть незначительным по сравнению с длительностью операции.
Естественно, ожидания на блокировках могут быть на различных данных в различных операциях ввиду пересечения на избыточных блокировках. Однако всё же каждая из этих операция может быть выполнена второй раз позднее на тех же данных за существенно меньшее время ввиду отсутствия одновременной с ней конкурирующей транзакции.
Какие (Где) ещё могут быть очереди:
- На уровне железа, например, к CPU или дисковой подсистеме;
- На уровне системы виртуализации, например, в результате ограничения доступных виртуальной машине аппаратных ресурсов;
- В результате использования механизмов синхронизации, например, на входе в критические секции, на защелках.
Желательно на первом шаге убедиться, что ожидания не возникают на аппаратных ресурсах. Для этих целей можно использовать инструменты:
- performance monitor;
- Подробнее можно прочитать в статье «Анализ загруженности оборудования для Windows» (https://kb.1c.ru/articleView.jsp?id=10)
- Для получения load average;
- Например, vmstat 1 для получения общей статистики с интервалом в секунду;
- Например, mpstat -P ALL 1 для получения информации по использованию всех CPU с интервалом в секунду;
- Например, iostat -xz 1 для получения информации по I/O операциям к дисковой подсистеме с интервалом в секунду;
- Например, free –m для получения информации по использованию оперативной памяти;
- Например, sar -n DEV 1 для получения информации по I/O по сетевым устройствам с интервалом в секунду;
- Например, sar –n TCP,ETCP 1 для получения статистики по использованию TCP с интервалом в секунду;
- для общего обзора работы процессов в системе Linux.
Мы не будем подробно останавливаться на этих инструментах, т.к. они не являются предметом этой методики.
На этом шаге также имеет смысл посмотреть с помощью strace (в Linux) или procmon (в Windows), нет ли колебаний производительности в результате каких-либо избыточных действий, которые могут проявить себя при рассмотрении системных вызовов (хотя чаще это просто не делают с надеждой, что тут все хорошо). Например, получить группировку по вызовам с помощью strace по процессам rphost можно таким образом:
for i in `pgrep rphost`; do echo «rphost » $i; time strace -r -f -p $i -e open,read,write,futex,stat,close,poll,lseek,openat,flock,recvfrom 2>&1 | head -n 100000 | sed -r ‘s/<\.\.\. //g’ | sed -r ‘s/ resumed/_resumed/g’ | sed -r ‘s/,? \».*\».*, /,
,/g’ | sed -r ‘s/lseek\([0-9]+, [0-9]+, /lseek( , ,/g’ | sed -r ‘s/, /,/g’ | awk ‘ END >>’ | sort -rnb | head; done Эта методика в первом шаге содержит анализ загруженности оборудования для того, чтобы избавиться от сомнений, что проблема действительно в ожиданиях на блокировках. Однако не правильно ограничиваться проверкой загруженности оборудования только на первом шаге, т.к. в процессе устранения ожиданий на блокировках вырастет параллельность работы. Таким образом, ожидающие ранее транзакции будут выполняться, потребляя аппаратные ресурсы. В результате нагрузка на оборудование может значительно возрастать. Отслеживать отсутствие очередей на аппаратных ресурсах необходимо на всем протяжении работы. Но не стоит путать отслеживание наличия проблемы с правильной последовательностью устранения технологических проблем. Например, правильной последовательностью в процессе проведения нагрузочного тестирования и устранения проблем в нагрузочном тесте является:
- Получение успешных и корректных функциональных тестов операций;
- Получение требуемой производительности при выполнении операций одним пользователем;
- Устранение ожиданий на транзакционных блокировках (управляемых и на СУБД) в многопользовательском нагрузочном тесте;
- Решение проблем очередей на других программных ресурсах системы;
- Решение проблем очередей на аппаратных ресурсах системы.
Шаг 2.
- возникают ли ожидания на управляемых блокировках (на уровне 1С:Предприятия 8);
- или изменяется ли именно время выполнения запросов с точки зрения 1С:Предприятия 8, включающее в себя ожидание на транзакционных блокировках.
(Для упрощения понимания в этой статье термин «управляемые транзакционные блокировки» сокращается до «управляемые блокировки», а под термином «транзакционные блокировки» подразумеваются «транзакционные блокировки на СУБД». Естественно, блокировки на СУБД и управляемые блокировки в контексте данной статьи являются транзакционными.)
Проще всего проверить ожидание на управляемых блокировках. Если есть ошибка, которая свидетельствует, что проблема на уровне СУБД, то естественно можно расследовать именно её и пропустить шаг анализа проблем на управляемых блокировках. Но в общем случае ошибки может и не быть.
Для расследования ожиданий на управляемых блокировках потребуется либо настроить технологический журнал (logcfg.xml) вида
либо в ЦУП (Центр Управления Производительностью, входящий в состав КИП (Корпоративного Инструментального Пакета)) добавить показатели сбора данных по ожиданиям на блокировках.
(рис.2. Выбор показателя производительности в ЦУП)
Лучше сразу добавить показатели из групп «Только блокировки 1С» и «Анализ»:
- Суммарное время ожидания на блокировках 1С;
- Максимальное время ожидания на блокировках 1С;
- Среднее время ожидания на блокировках 1С;
- Количество текущих ожиданий на блокировках 1С;
- Анализ ожиданий на блокировках.
В случае настройки (на этом шаге) технологического журнала вам в первую очередь потребуется найти события TLOCK с непустым полем WaitConnections, например:
В поле WaitConnections указывается номер t:connectID (идентификатора соединения, не изменяющегося в пределах транзакции), ожидание которого имело место при попытке установки управляемой блокировки.
Найти такие события можно, например, так:
Найти ожидания, которые, скорее всего, привели к таймаутам на управляемых блокировках, можно, например, так:
Т.е. такие ожидания, которые выполнялись длительное время, однако нужно помнить, что максимальное время ожидания настраивается в конфигураторе в меню «Администрирование \ Параметры информационной базы \ Время ожидания блокировки данных (в секундах)».
Из текста события сразу становится понятно:
- Контекст, где было ожидание (для события выше)
- ОбщийМодуль.ПоказателиПроизводительности.Модуль : 1994 : СообщениеМенеджерЗаписи.Удалить();
- InfoRg404.DIMS
- InfoRg404.DIMS Exclusive Fld405=4216B7C0FEBDF74182BCEFF80930A8AD Fld406=51:ae237dae58d1d6c94b4e42c1ab63e0c1 Fld407=T»20180510092101″ Fld408=00000000000000000000000000000000
Далее потребуется найти в пределах транзакции (в примере настройки logcfg.xml выше указаны события SDBL относительно начала и окончания транзакции) события TLOCK с найденным t:connectID (т.е. WaitConnections=16) по тому же пространству. Например, это можно сделать так:
- Ожидающую транзакцию (транзакцию жертву);
- Ожидаемую транзакцию (виновную транзакцию).
В ожидающей транзакции было затрачено ненулевое время на ожидание возможности установить блокировку (это касается и ожидания блокировок на уровне СУБД). В ожидаемой транзакции такое время могли и не тратить, т.е. блокировка могла установиться «сразу». По этой причине, не стоит искать блокировки ожидаемых (виновных) транзакций в журналах или трассировках, собранных с каким-либо ограничением по длительности, т.к. этих блокировок может там и не быть.
Лучше всего при расследовании помнить следующие правила:
- Управляемые блокировки удерживаются до конца транзакции;
- Управляемые блокировки в рамках одной транзакции совместимы;
- Управляемые блокировки по различным пространствам или данным совместимы;
- Управляемые блокировки, имеющие совместимые типы, совместимы;
- Если какое-то измерение пространства в управляемой блокировке пропущено, то это эквивалентно блокировке всего измерения (любых его значений) этого пространства.
По сути, вам потребуется:
- Найти все пересечения;
- Сгруппировать их по контекстам на встроенном языке;
- Выстроить в порядке убывания суммарного времени ожидания на блокировках.
В случае использования ЦУП расследование будет выполнено автоматически по ожиданиям на управляемых блокировках, а также по ожиданиям на транзакционных блокировках на СУБД. От вас не потребуется ничего, кроме как нажать кнопку «Анализ».
В случае нехватки времени или опыта рекомендуем использовать ЦУП.
(рис.3. Анализ проблем производительности в ЦУП)
При выборе любой из строк группировки контекстов, вы сможете обнаружить детализацию по выявленным проблемам.
(рис.4. Анализ ожиданий на блокировках в ЦУП)
Выбрав, например, «Ресурс», вы сможете увидеть детализацию по всем полям, которые были указаны в блокировке.
(рис.5. Детализация измерений управляемой блокировки в ЦУП)
Обращаем внимание, что вы сможете:
- Сгруппировать по контексту в целом;
- По первой строке контекста;
- По последней строке контекста;
- Упорядочить группировку:
- по суммарному времени, затраченному на ожидания определенного типа,
- по среднему времени,
- по максимальному времени (скорее интересно для расследования длительного выполнения запросов).
Шаг 3.
Допустим, мы не обнаружили на шаге 2 никаких ожиданий на управляемых транзакционных блокировках, которые могли бы составить искомое замедление скорости выполнения операции.
Таким образом, мы смотрим в сторону выполнения запросов в СУБД.
Время выполнения запросов с точки зрения платформы 1С:Предприятия 8 может изменяться:
- В результате ожиданий на транзакционных блокировках;
- В результате выбора различных планов запросов;
- В том числе после пересчета статистики, выполнения VACUUM и т.д.;
- Например, в блоге MSDN есть упоминание, что в некоторых версиях MS SQL Server перекомпиляция планов запросов может зависеть от изменяемости содержимого локальных временных таблиц (https://blogs.msdn.microsoft.com/sqlprogrammability/2007/01/18/11-0-temporary-tables-table-variables-and-recompiles); таким образом, имеются примеры перекомпиляции планов запросов при неизменении текста запроса и его параметров;
Т.е. на этом шаге мы снова либо выполняем серьезное предположение, что дело именно в ожиданиях на транзакционных блокировках (например, потому что мы видели соответствующие ошибки в технологическом журнале), либо мы заранее исключили все другие варианты (ожидания на каких-либо других ресурсах). (Рассматриваем управляемый режим управления блокировками данных, иначе шаг 2 оказывается избыточным).
Расследование с помощью ЦУП
При сборе аналитики с помощью ЦУП «Анализ ожиданий на блокировках» с целью экономии времени разработчика в будущем автоматически добавляется показатель «Анализ запросов», подразумевая, что ожидания на блокировках являются только одной из возможных причин колебаний времени выполнения запросов.
Повторим, что в случае использования ЦУП ничего дополнительно делать не потребуется, т.к. разобранный анализ будет уже включать в себя ожидания на блокировках на уровне СУБД.
В случае выбора «Блокировка СУБД» вы сможете увидеть сначала небольшую детализацию о запросах, которые участвовали в ожидании.
(рис.6. Детализация по блокировке на уровне СУБД в ЦУП)
Однако по двойному щелчку по строке в разделе «Запросы» по заблокированному или блокирующему контексту, вы увидите детализацию по этим запросам,
(рис.7. Стек запроса из аналитики ожидания установки блокировки в ЦУП)
а также по блокировкам.
(рис.8. Детализация по блокировке на уровне СУБД в ЦУП)
Расследование с помощью технологического журнала платформы 1С:Предприятие 8
Для того, чтобы собрать аналогичную информацию вручную, для MS SQL Server потребуется воспользоваться различными инструментами.
В системе (если не запрещено требованиями назначения функциональности) постоянно работает «Сервис вспомогательных функций кластера», который обеспечивает периодическое выполнение запроса (например, для MS SQL Server) в rphost-ах кластера вида
SELECT spid, blocked FROM master.dbo.sysprocesses WITH(NOLOCK) WHERE blocked > 0 AND lastwaittype LIKE ‘LCK_%’
для получения информации о блокировках, и фиксирует их в событиях в технологическом журнале.
Свойства таких событий:
? lka=‘1’ – поток является источником блокировки.
? lkp=‘1’ – поток является жертвой блокировки.
? lkpid – номер запроса к СУБД, «кто кого заблокировал» (только для потока-жертвы блокировки). Например, ‘423’.
? lkaid – список номеров запросов к СУБД, «кто кого заблокировал» (только для потока-источника блокировки). Например, ‘271,273,274’.
? lksrc – номер соединения источника блокировки, если поток является жертвой, например, ‘23’.
? lkpto – время в секундах, прошедшее с момента обнаружения, что поток является жертвой. Например: ‘15’.
? lkato – время в секундах, прошедшее с момента обнаружения, что поток является источником блокировок. Например, ‘21’.
Записи таких событий в технологическом журнале могут помочь в понимании общей картины проблемы, но не являются единственным средством для расследования ожиданий на транзакционных блокировках.
Расследование с помощью стандартного отчета MS SQL Server и средств платформы 1С:Предприятие 8
В случае наличия воспроизведения проблемы в MS SQL Server можно воспользоваться отчетом по динамическим представлениям «Top Transactions by Locks Count», который позволит увидеть транзакции, которые удерживали наибольшее число блокировок.
(рис.9. Стандартный отчет по транзакция с блокировками в MS SQL Server Management Studio)
Однако получить соответствие таблиц в базе данных именам таблиц информационной базы придется отдельно, воспользовавшись методов встроенного языка 1С:Предприятия 8 ПолучитьСтруктуруХраненияБазыДанных() .
Для того, чтобы получить соответствие запросов, установивших транзакционные блокировки на СУБД, контекстам встроенного языка, потребуется собрать технологический журнал. Для случая работы с MS SQL Server или PostgreSQL он будет выглядеть так:
Запросы будут содержать искомые контексты на встроенном языке 1С:Предприятия 8. Стоит обратить внимание, что в этом примере настройки добавлен сбор планов запросов <plansql/>, который внесет дополнительные накладные расходы на сбор данных, однако позволит в случае нахождения подозреваемых запросов сразу посмотреть на план запросов и сделать выводы о проблемах. Без настройки <plansql/> сбор планов запросов по умолчанию не происходит.
Получение детальной информации по ожиданиям на транзакционных блокировках в MS SQL Server
Для получения более подробной информации о том, что происходит на уровне СУБД MS SQL Server можно воспользоваться MS SQL Profiler или механизмом расширенных событий.
MS SQL Server Profiler
В случае относительно небольшой нагрузки на рабочей системе (не более нескольких сотен пользователей, одновременно работающих в системе в обычном темпе) возможно собрать дополнительную информацию с помощью MS SQL Profiler.
(рис.10. Настройка трассировки в MS SQL Server Profiler)
Включать сбор такой трассировки лучше не из интерфейса, а преварительно сохранив трассировку в виде скрипта для запуска сбора трассировки на сервере. Это необходимо сделать для уменьшения возможного падения производительности в процессе сбора собираемых данных в рабочей системе.
(рис.11. Сохранение трассировки MS SQL Server Profiler в виде скрипта для запуска сбора трассировки на сервере)
В полученном скрипте стоит обратить внимание на возможность регулировки объема собранной трассировки, а также на комментарий, обязывающий изменить путь сбора данных.
При сборе данных с помощью трассировки MS SQL Profiler стоит помнить, что:
- События класса Lock:Acquired означают, что соответствующая блокировка была успешно установлена;
- Следует постараться ограничить трассировку только сбором данных по рассматриваемой базе данных (например, указав DatabaseID);
- В случае рассмотрения только (!) ожиданий на блокировках возможно добавить фильтр по Duration, но тогда в трассировке не будет успешно установленных блокировок, которые установились без ожидания быстрее времени, заданного в фильтре;
- Выгодно собирать трассировку с указанием всех колонок (Show all columns), если вы до конца не уверены в том, какие именно данные вы должны получить на выходе (если уверены, собирайте только то, что вам действительно нужно);
- Собранную трассировку проще всего анализировать, сохранив в таблицу в специально созданную для этого пустую базу данных.
Механизм расширенных событий (Extended events)
В случае значительной нагрузки (тысячи пользователей, одновременно работающих в одной информационной базе) имеет смысл вместо MS SQL Profiler воспользоваться механизмом расширенных событий.
(рис.12. Настройка сбора расширенных событий в MS SQL Server Management Studio)
Обратите внимание на событие blocked_process_report.
Для его настройки потребуется также установить в свойствах экземпляра сервера в разделе Advanced параметр «Blocked Process Threshold» в число секунд, по превышению которых будет сформировано событие. Для MS SQL Server также можно воспользоваться следующим способом:
(рис.13. Изменение общих свойств экземпляра сервера в MS SQL Server Management Studio)
Собранную трассировку вы сможете загрузить в таблицу, это стоит делать, т.к. анализ путем «просмотра глазами» кажется достаточно неудобным.
Для этого необходимо создать таблицу, затем можно воспользоваться sys.fn_xe_file_target_read_file для загрузки трассировки в эту таблицу, например:
— загрузка данных трассировки в таблицу для ms sql 2012+
Необходимо обратить внимание, что список полей в примере выше может меняться в зависимости от настройки сбора расширенных событий. При выполнении настроек нужно внимательно проверить состав полей, создаваемых в таблице и загружаемых в нее. Это можно сделать, сохранив настроенную трассировку в виде скрипта. В противном случае вы можете не увидеть все данные, которые вы собирали.
При детальном рассмотрении ожиданий на блокировках на уровне СУБД необходимо помнить, что механизмы СУБД могут устанавливать блокировки не на то, на что вы на самом деле думаете или ожидаете. Реализованная логика может быть куда сложнее того, что покажется на первый взгляд. Но всё же иногда может потребоваться заглянуть чуть глубже, чтобы немного больше понять суть происходящего. Например, пересечение двух транзакций может также возникнуть в результате особенностей реализации механизмов в конкретной СУБД. Допустим, мы видим, что две транзакции пересеклись на определенной странице, хотя данные различны, а планы запросов не подразумевают пересечений. Но обычно такого не происходит. Как же увидеть детали, когда мы видим пересечение двух транзакций с различными данными?
(рис.14. Пример ресурса в пересечении двух транзакций в MS SQL Server)
Например, видим, что Resourse (для Type = PAGE) 1:1026.
В этом случае увидеть детали поможет включение trace флага 3604:
DBCC TRACEON(3604, -1);
После включения trace флага появляется возможность (например, по базе ‘test’) получить детали, например, так:
DBCC PAGE(‘test’, 1, 1026, 3);
В полученном выводе можно увидеть данные страницы, где было пересечение. Необходимо не забыть выключить trace флаг после получения необходимых для расследования данных:
DBCC TRACEOFF(3604, -1);
В случае необходимости расследования ожиданий на СУБД PostgreSQL необходимо знать, что разработчики 1С:Предприятия 8 считают, что ожиданий на СУБД PostgreSQL при использовании управляемого режима управления блокировками данных возникать не должно, ожидания должны возникать только на управляемых блокировках. Все сценарии работы с 1С:Предприятием 8 и СУБД PostgreSQL, в которых ожидания не возникли на уровне управляемых блокировок, но воспроизвелись на уровне PostgreSQL, необходимо документировать и отправлять информацию разработчикам в тех поддержку на v8@1c.ru или по адресу CorpTechSupport@1c.ru, если проблема мешает в работе корпоративному клиенту. Однако даже в случае их нахождения это все равно ошибки, которые необходимо устранять, не дожидаясь предложений по решению от фирмы «1С».
Расследование в PostgreSQL
Для получения списка текущих установленных блокировок в PostgreSQL можно воспользоваться представлением pg_locks, например:
(рис.15. Пример наложенных блокировок в PostgreSQL)
Для получения текста запроса можно воспользоваться представлением pg_stat_activity, например:
(рис.16. Пример запроса, полученного из представлений в PostgreSQL)
Получить информацию о транзакциях, ожидающих на транзакционных блокировках в PostgreSQL можно, например, следующим запросом:
Для включения сбора данных об ожиданиях в журнал PostgreSQL необходимо добавить секцию log_lock_waits = on в postgresql.conf. Тогда настройка журналов в postgresql.conf может выглядеть так:
(рис.17. Пример пересечения двух транзакций в PostgreSQL)
В случае сбора журналов в PostgreSQL иногда удобнее рассматривать журналы не в текстовом представлении, а в виде проанализированного отчета в html. Для этого можно воспользоваться инструментом PgBadger.
Таким образом, можно заметить, что сбор данных по ожиданиям на блокировках на уровне СУБД является реальной задачей, но достаточно трудоемкой без использования ЦУП.
Если вы всё же решились расследовать ожидания на блокировках без использования ЦУП, то общий подход на этом шаге будет такой:
- найти транзакции, участвующие в конфликте блокировок;
- найти ресурс, на котором произошло пересечение;
- найти запрос, при выполнении которого попытались, но не смогли установить транзакционную блокировку; проанализировать план этого запроса на предмет ошибки;
- найти момент или запрос, при выполнении которого в другой транзакции ранее успешно установили конфликтующую блокировку; убедиться, что данные отличаются; проанализировать план этого запроса на предмет ошибки;
- проанализировать причины и пути сокращения длительности транзакции, в которой была успешно установлена конфликтующая транзакционная блокировка.
Трассировка MS SQL Profiler, расширенные события для MS SQL Server или журнал PostgreSQL позволят вам найти транзакции, ресурсы, запросы. Но для получения соответствия найденных данных коду в конфигурации 1С:Предприятие 8 потребуется собирать технологический журнал и/или пользоваться методом встроенного языка 1С:Предприятия 8 ПолучитьСтруктуруХраненияБазыДанных(). Например, аналогичный сбор и сопоставление полученных данных MS SQL Server выполняет ЦУП.
Таким образом, способы устранения проблем сводятся к двум основным возможностям:
- убираем избыточную блокировку;
- сокращаем длительность периода, в течение которого блокировка была установлена.
Шаг 4.
Собрав необходимые данные, разработчик должен ответить на вопросы:
- Какая транзакция получила ошибку или ожидала какое-либо время и является жертвой ожидания на транзакционной блокировке? (Таких транзакций может быть много, но стоит начинать всегда с самых длительных или наиболее часто повторяемых ожиданий, если нет других вводных).
- В рамках какой длительной транзакции (транзакции-виновника) была ранее успешно установлена несовместимая транзакционная блокировка? Что выполнялось в транзакции-виновнике, что привело к длительному удержанию транзакционной блокировки?
Нужно понимать, что нельзя просто убрать транзакционную блокировку, т.к. она нужна для обеспечения целостности. Пути решения могут быть следующие, если точно известно, что пересечение транзакций произошло на разных данных с точки зрения пользователей (и не требуется корректировка бизнес-процесса):
как узнать, каким пользователем заблокирован документ?
нет там этой информации. Нет на уровне системы. Только если в среде 1С организуешь.
В скуле можно узнать, кто блокировал.
В нетвари можно узнать, кто блокировалНо это даже не на уровне ОС, а на уровне сетевой ОС или самого скуля.
Ты не понимаешь работы механизма блокировки. Он разный при блокировке на уровне ОС, сетевой ОС, файловой базы, скульной базы.
Общепринятым стандартом в случае, если делается попытка блокировки записи, уже кем то блокированной, то не предусмотрен возврат имени пользователя, блокировавшего запись. Только флаг — Выполнено/Отказано. Вот так просто сделали, хотя возврат имени был бы очень желателен.
информацию о блокировке (включая имя пользователя) можно посмотреть в скульном мониторе, в мониторе сетевой ОС, в мониторе файловой базы. Но в программных запросах оно не возвращается.
P.S. но может возвращаться, если в продукте есть специальный АПИ (такой есть, напрмер, в новеле — но надо работать на нормальном языке или писать ДЛЛ)
(33) ну-у-у. Для этого нужно всё «раскручивать взад».. но платформа таких механизмов не даёт.
(32) и-и-и.. Вы знаете функцию 1С которая Вам вернёт информацию о соединениях в сиквеле.
Вот по поводу 7.7. Но я думаю, что по аналогии можно что-нибудь придумать.
Пока искал ссылку, появился пост (31). Похоже, что так и есть. В 7.7-то разные юзеры в sql сидели. Чорт.
а можно как-либо методом исключения выявить?
Хотя бы узнать хоть что-то тот пользователь заблокировал или нет?Для каждого Пользователь Из СписокАктивныхПользователь Цикл
Если ХотяБыОдинОбъектИмЗаблокирован(Пользователь) Тогда
// цикл по заблокированным объектам(38) а какая разница? для файловой всё просто более дубовей. При работе юзера с таблицей, на таблице устанавливается признак блокировки. Но это «флажёк».. в нём априори (для повышения того же быстродействия) НЕТ информации об источнике и причине блокировки. просто «состояние» — блокировано.
Отсюда и растут всё «ноги». Если так уж важно отслеживать что, где, когда.. То тогда имхо нужно дорабатывать сам документ, что бы он сам где-нибуть регистрировал того юзера, который в данное время делает «чёрное дело» :-)))
Пессимистическая блокировка объекта (документа, справочника и т.д)
Иногда надо блокировать объект, например элемент справочника, чтобы другой пользователь не смог внести параллельно данные в его свойства. Для этого можно использовать метод объекта Заблокировать(), например СправочникОбъект.Заблокировать(). Метод не доступен на клиенте.
Если объект уже заблокирован, то при попытке заблокировать выйдет ошибка с исключением.
Проверить, заблокирован ли объект можно с помощью метода объекта Заблокирован() (булево), например
Если НоменклатураОбъект.Заблокирован() Тогда
НоменклатураОбъект.Разблокировать();
КонецЕсли;Для разблокировки соответственно надо использовать метод Разблокировать().
В форме клиентского приложения заблокировать объект можно с помощью метода ЗаблокироватьДанныеДляРедактирования(<Ключ>, <ВерсияДанных>, <ИдентификаторФормы>), где:
ВерсияДанных — строка. Необязательный.
ИдентификаторФормы — уникальный идентификатор формы в рамках которой заблокирован объект. Может Быть не указан Если параметр не указан, то блокировка устанавливается на ограниченное время и может быть снята:
- с помощью метода РазблокироватьДанныеДляРедактирования() без указания идентификатора формы;
- при окончании транзакции, если блокировка установлена в транзакции;
- при окончании работы встроенного языка (для режимов запуска "Тонкий клиент" и "Веб-клиент"; при возврате управления с сервера);
- при завершении сеанса.
Если ИдентификаторФормы указан, то блокировка автоматически снимается после закрытия формы или с помощью метода РазблокироватьДанныеДляРедактирования(<Ключ>, <ИдентификаторФормы>), где ИдентификаторФормы соответствует значению вызванному при блокировке.
Вызывает исключение, если объект уже заблокирован, в том числе и методом Заблокировать().
Не доступен на клиенте.
&НаСервере
Процедура ЗаблокироватьАбонента(Абонент)Попытка
ЗаблокироватьДанныеДляРедактирования(ТекущийАбонент.Ссылка,,ЭтаФорма.УникальныйИдентификатор);
ЗаблокированныйАбонент = ТекущийАбонент.Ссылка;
Исключение
// Если попали в исключение, то значит этот абонент уже открыт у какого то пользователя
// выведем сообщение о блокировке и откроем пустого абонента
НашеОписаниеОшибки = ОписаниеОшибки();
ОбрезанноеСообщение = Прав(НашеОписаниеОшибки, СтрДлина(НашеОписаниеОшибки) — Найти(НашеОписаниеОшибки, "Объект уже заблокирован") + 1);
ОбрезанноеСообщение = СтрЗаменить(ОбрезанноеСообщение, Символы.Пс, " ");
ОбрезанноеСообщение = СтрЗаменить(ОбрезанноеСообщение, "Объект уже заблокирован", "Абонент " + Абонент + " заблокирован");
ОбрезанноеСообщение = ОбрезанноеСообщение + Символы.ПС + "Абонент открыт только на просмотр!";
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОбрезанноеСообщение, , , , УникальныйИдентификатор);ТолькоПросмотр = Истина;
КонецПопытки;В результате выполнения получим ошибку: "Абонент Иванов Иван Иванович заблокирован: компьютер: Мой-компьютер, пользователь: Администратор, сеанс: 422, начат: 12.09.2022 в 16:15:27, приложение: Тонкий клиент
Абонент открыт только на просмотр!"Оптимистическая блокировка объекта.
Оптимистическая блокировка запрещает запись объекта в базу данных, если после считывания объекта он был изменен в базе данных другими сеансами или другими программными объектами этого же сеанса.
Фактически, оптимистическая блокировка представляет собой проверку, которая выполняется перед записью объекта в базу данных. Эта проверка построена на анализе номера версии объекта, хранящейся в базе данных и номера версии, помещенной в память компьютера в момент считывания данных из информационной базы. Если при записи объекта номера его версий отличаются, то будет выдано предупреждение о том, что версия объекта изменилась или он был удален, то есть сработает оптимистическая блокировка.
Просмотр заблокированных строк в 1С
Раньше приходилось отвечать, что инструмента, который показывает все вышеописанное, сейчас просто нет. Но потом мне это надоело, и я решил сделать собственный инструмент, который позволяет ответить на все вышеописанные вопросы.
Данный инструмент создавался в первую очередь для слушателей курса по оптимизации, для демонстрации, какие блокировки, когда и на что будут установлены.
Инструмент не является конкурентом для ЦУП или облачного сервиса анализа блокировок, он предназначен в первую очередь для обучения и ознакомления с работой блокировок, а не для анализа ожиданий на блокировках.
Все инструменты на текущий момент показывают только информацию постфактум, когда ожидание уже случилось. Данный инструмент показывает ситуацию на текущий момент.
В некоторых случаях обработка может использоваться и для задач по оптимизации. Например, при переводе конфигурации на упр. режим, можно будет легко и быстро посмотреть, на какие именно записи была наложена управляемая блокировка.
Также можно в моменте посмотреть, что именно сейчас блокирует каждый из пользователей, и кто кого ждет.
Сразу скажу что обработка работает не быстро, но такая цель и не ставилась. При этом следует учитывать, что работа возможна только с СУБД MS SQL Server и только в управляемом приложении.
Если ожидание идет на сервере СУБД, тогда можно увидеть, на каком именно ресурсе идет ожидание, в колонке статус будет значение «Ожидание». Для блокировок 1С посмотреть, на чем идет ожидание, не получится, т.к. сервер 1С просто не пишет эту информацию в логи в момент ожидания, она туда попадает только после того, как ожидание завершится.
Для использования обработки необходимо сначала заполнить настройки.
Обработку надо обязательно открывать в той же базе, блокировки которой вы хотите посмотреть.
Если вы хотите видеть информацию по управляемым блокировкам, тогда необходимо включить флаг «Отображать блокировки 1С». Следует учитывать, что этот функционал является тестовым, возможны ошибки при отображении, когда пользователей несколько, к тому же блокировки будут отображаться только если в кластере один сервер.
Через 60 сек. будет включен технологический журнал, и данные об установленных управляемых блокировках начнут собираться.
Для отображения данных необходимо нажать «Обновить».
В данном случае видно, что администратором наложены как блокировки СУБД, так и блокировки 1С (выделены жирным).
Если блокировка СУБД наложена на кластерный индекс, тогда можно посмотреть, какие именно записи заблокированы, сделав двойной клик. При этом в таблице ниже будут отображены все заблокированные записи в терминах 1С. Например, здесь видно, что в таблице итогов регистра ТоварныеЗапасы заблокирована одна строка с итогом за октябрь и одна строка с текущими итогами.
Если блокировка СУБД наложена на некластреный индекс, тогда, к сожалению, заблокированные записи посмотреть не получится.
Если это блокировка 1С, тогда независимо от пространства блокировок можно будет всегда посмотреть, что именно заблокировано.
При желании можно включить отображение служебных блокировок СУБД (флаг «Отображать блокировки намерения и стабильности схемы»). Мне сложно представить, кому и зачем на практике может понадобиться этот флаг, разве что таким же маньякам, как я
Хотя, возможно, кто-то будет к 1С:Эксперт готовиться и захочет «потрогать руками» служебные блокировки СУБД, а то про них говорят и спрашивают, но никто не показывает.
На данном рисунке ясно видно блокировку намерения на страницу и таблицу.
Если в момент нажатия кнопки Обновить в базе было ожидание на блокировке, то это будет отображено в верхней таблице.
Данный рисунок показывает, что продавец ждет администратора, при этом можно поглядеть установленные блокировки обоих пользователей.
Если вы используете управляемый режим блокировок, то не удивляйтесь, что на уровне СУБД обработка почти всегда будет показывать только X блокировки. Просто S блокировки будут сниматься сразу после чтения, не дожидаясь конца транзакции, поэтому верятность их поймать крайне низка.
В автоматическом режиме блокировок работать с обработкой интереснее, например, можно поставить точку останова после Запрос.Выполнить() в транзакции и посмотреть, какие именно записи заблокировал этот запрос. Если запрос заблокировал лишнее (то что не подходит под его условия), вы сразу это увидите.
Надеюсь, что данная обработка поможет вам лучше понять работу блокировок на практике и сподвигнет на самостоятельные эксперименты в этой области. Особенно это будет полезно при подготовке к экзамену 1С:Эксперт.