Анализ взаимоблокировок
База данных - HighLoad оптимизация
Вступление
Анализ взаимоблокировок описан на ИТС, там же пошаговая инструкция. Предлагают анализировать файл технологического журнала в блокноте. Ниже Bash-скрипт для получения информации из технологического журнала по событиям TTIMEOUT, TDEADLOCK, TLOCK.

Пропустим установку Bash и сбор технологического журнала.
Упрощенная (первая) версия.
egrep '^[0-9][0-9].{10,24},TLOCK.*WaitConnections=[0-9]' -h -R \
| awk -F'(:.{8,21},TLOCK.*t:connectID=)|(,SessionID=.*,Regions=)|(,Locks=.*WaitConnections=)|(,connectionID=)' \
'BEGIN {print "#!/bin/bash" > "2step.sh"} \
{cow[$3,$2,$1]="egrep '\''^"$1"\.{10,25},TLOCK.*t:connectID="$2".*,Regions="$3".*WaitConnections="$4"'\'' -h -R"; \
tiger[$3,$2,$1]="egrep '\''^"$1"\.{10,25},TLOCK.*t:connectID="$4".*,Regions="$3".*WaitConnections=,'\'' -h -R"; \
timeout[$3,$2,$1]="egrep '\''^"$1"\.{10,25},TTIMEOUT.*t:connectID="$2".*WaitConnections="$4"'\'' -h -R";} \
END {for (item in cow) {print cow[item]"\n"timeout[item]"\n"tiger[item]"\n"tiger1[item] >> "2step.sh"; }}' \
; ./2step.sh
Комментарии к коду:
1. выбираем возможные жертвы с непустым временем ожидания. Предполагаем, что порядок тегов событий TLOCK не изменяется.
2. разделители подобраны таким образом, что $1 минута события, $2 ID соединения жертвы, $3 область блокировки, $4 ID соединения виновника
3. очищаем файл шаблона запроса 2step. Первая строка командного скрипта bash должна быть стандартной #!/bin/bash.
4. заполняем текстовые переменные cow (жертва), tiger (виновник), timeout для шаблона запроса egrep.
5. эти шаблоны предполагают, что минута времени виновника и жертвы совпадают. Конечно, можно проверять предыдущую минуту, например "egrep '\''^"$1-1"\.{10,25},TLOCK.*t:connectID="$4".*, Regions="$3".*WaitConnections=,'\'' -h -R"; и более ранние события. Но мы не будем распространятся в эту сторону: такие ситуации могут возникать только при очень длительных блокировках, которые являются совершенным злом, их необходимо анализировать отдельно. Очень трудно было напечатать одинарную кавычку в шаблон из кода awk. Наконец нашел конструкцию: внутри двойных кавычек открывается одинарная кавычка, слэш одинарная кавычка, одинарная кавычка. На выходе имеем одинарную кавычку.
6. после обработки событий TLOCK всех возможных жертв, выводим в файл 2step запрос по шаблону
7. выполняем файл 2step.sh. Выходят события жертвы блокировки, виновника блокировки, запись TTIMEOUT.
Первая версия прекрасно работает, но есть возможности ее улучшить: дополнительно группировать события по области блокировки (Regions), добавить события DEADLOCK.
Основная версия скрипта:
#!/bin/bash
egrep '^[0-9][0-9].{10,24},TLOCK,.*WaitConnections=[0-9]' -H -R --include "200311*.log" \
| awk -F'(^.{1,20}\/)|(.log:)|(:.{8,21},TLOCK,.*t:connectID=)|(,SessionID=.*,Regions=)|(,Locks=.*,WaitConnections=)|((,connectionID=)|(,Context=))' \
'BEGIN {print "#!/bin/bash" > "2step.sh"} \
{gsub("'\''",".",$5) \
; ord[$3,$5,$4]="Time"$3"Regions"$5"Tiger"$6"EndOrder" \
; cow[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TLOCK.*t:connectID="$4".*,Regions="$5".*WaitConnections="$6"'\'' -h -R --include "$2".log" \
; tiger[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TLOCK.*t:connectID="$6".*,Regions="$5".*WaitConnections=,'\'' -h -R --include "$2".log" \
; deadlock[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TDEADLOCK.*t:connectID="$4".*DeadlockConnectionIntersections=."$4"."$6"'\'' -h -R --include "$2".log" \
; timeout[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TTIMEOUT.*t:connectID="$4".*WaitConnections="$6"'\'' -h -R --include "$2".log";} \
END {for (K in ord) \
{print ord[K]cow[K]"\n"ord[K]timeout[K]"\n"ord[K]deadlock[K]"\n"ord[K]tiger[K]"\n"ord[K]"echo "; }}' \
| sort -rnb \
| awk -F'^.*EndOrder' '{print $2;}' >> "2step.sh" \
; ./2step.sh >> "result.txt"
Комментарии к коду: скрипт запускать из среды Bash в каталоге, где собраны подкаталоги rphost за день. В моем случае объем за день 3 Гб, 4 каталога rphost, 66 файлов. Время работы скрипта на моем компьютере – 10 Минут. Скрипт находит события не только по которым зафиксировано TTIMEOUT или TDEADLOCK, но и ожидания на блокировках.
1. Выбираем файлы по маске, например 200311*.log с событиями TLOCK, которые имели ожидание. Выборка включает имя файла.
2. Разделители awk подобраны так, что: $2 краткое имя файла, $3 Минута события, $4 ConnectID жертвы, $5 Область блокировки, $6 ConnectID виновника. Оказывается, после ConnectID виновника может быть тег connectionID ИЛИ Context. Порядок тегов очень важен.
3. Очищаем файл шаблона запроса 2step. Первая строка командного скрипта bash должна быть стандартной #!/bin/bash.
4. Область блокировки может содержать одинарные кавычки, от этого страдает построение шаблона запроса. Заменяем одинарные кавычки на точку.
5. Заполняем выражение упорядочивания: область, виновник, жертва.
6. Заполняем текстовые переменные cow (жертва), tiger (виновник), timeout, deadlock для шаблона запроса egrep. Используем допущение, что час и минута всех файлов всех событий одной взаимоблокировки совпадают.
7. Формируем шаблон запроса, между группами строк выводим echo
8. Сортируем по области блокировки
9. Убираем область сортировки, помещаем шаблон запроса в файл.
10. Выполняем шаблон запроса.
Дополнительные бонусы:
Скрипт для поиска длительных транзакций
#!/bin/bash
printf "%15s\t\t%s", "Duration(sec.)", "Event string" \
; echo \
; egrep '^.{12,25},SDBL,.*Func=(Commit|Rollback)Transaction' -h -R --include "$@" \
| awk -F'(-|,)' '{printf "\n%4d\t%s", $2/1000000, $0}' \
| sort -rnb \
| head
Комментарии к коду:
- Обязательная первая строка bash-скрипта
- Заголовок таблицы
- Отделяем заголовок от таблицы
- Выбираем события SDBL, маску файла берем из параметра командной строки.
- Печатаем длительность в секундах, строку события.
- Сортируем
- Выводим первые 10 строк.
Вариант скрипта анализа взаимоблокировок без сортировки
#!/bin/bash
egrep '^[0-9][0-9].{10,24},TLOCK,.*WaitConnections=[0-9]' -H -R --include "$@" \
| awk -F'(^.{1,20}\/)|(.log:)|(:.{8,21},TLOCK,.*t:connectID=)|(,SessionID=.*,Regions=)|(,Locks=.*,WaitConnections=)|((,connectionID=)|(,Context=))' \
'BEGIN {print "#!/bin/bash" > "2step.sh"} \
{gsub("'\''",".",$5) \
;ord[$5]=$5 \
;cow[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TLOCK.*t:connectID="$4".*,Regions="$5".*WaitConnections="$6"'\'' -h -R --include "$2".log" \
;region[cow[$3,$5,$4]]=$5 \
;tiger[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TLOCK.*t:connectID="$6".*,Regions="$5".*WaitConnections=,'\'' -h -R --include "$2".log" \
;deadlock[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TDEADLOCK.*t:connectID="$4".*DeadlockConnectionIntersections=."$4"."$6"'\'' -h -R --include "$2".log" \
;timeout[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TTIMEOUT.*t:connectID="$4".*WaitConnections="$6"'\'' -h -R --include "$2".log";} \
END {for (L in ord) { print "echo " >> "2step.sh"; \
for (K in cow) { if (region[cow[K]]==ord[L]) \
{print cow[K]"\n"timeout[K]"\n"deadlock[K]"\n"tiger[K] >> "2step.sh";} \
}}}' \
; ./2step.sh >> "result.txt"
Обновление от 26/07/2022
Всем привет ! Решил упростить обработку, переделал колонки в AWK. Обратите внимание на один нюанс: обработка ищет проблемы не по ключевым словам TDEADLOCK, TTIMEOUT а анализирует все ненулевые ожидания.
#!/bin/bash
egrep '^.{20,30},TLOCK,.*WaitConnections=[0-9]' -H -R --include "*.log" \
| awk -F'(:)|(.connectID=)|(,SessionID.*,Regions=)|(,Locks=.*,WaitConnections=)|(,Context=)|(,connectionID=)' \
'BEGIN {print "#!/bin/bash" > "2step.sh"} \
{gsub("'\''",".",$9) \
;ord[$9]=$9 \
;cow[$2,$9,$8]="egrep '\''^"$2"\.{10,25},TLOCK.*t:connectID="$8".*,Regions="$9".*WaitConnections="$10"'\'' -h -R --include "$1 \
;region[cow[$2,$9,$8]]=$9 \
;tiger[$2,$9,$8]="egrep '\''^"$2"\.{10,25},TLOCK.*t:connectID="$10".*,Regions="$9".*WaitConnections=,'\'' -h -R --include "$1 \
;deadlock[$2,$9,$8]="egrep '\''^"$2"\.{10,25},TDEADLOCK.*t:connectID="$8".*DeadlockConnectionIntersections=."$8"."$10"'\'' -h -R --include "$1 \
;timeout[$2,$9,$8]="egrep '\''^"$2"\.{10,25},TTIMEOUT.*t:connectID="$8".*WaitConnections="$10"'\'' -h -R --include "$1;} \
END {for (L in ord) { print "echo " >> "2step.sh"; \
for (K in cow) { if (region[cow[K]]==ord[L]) \
{print cow[K]"\n"timeout[K]"\n"deadlock[K]"\n"tiger[K] >> "2step.sh";} \
}}}' \
; ./2step.sh >> "result.txt"
Если у Вас что-то не получается - обращайтесь, будем думать вместе.
Благодарю Виктора Богачева за предоставленные методические материалы и поддержку.
Вступайте в нашу телеграмм-группу Инфостарт
tlock tdeadlock взаимоблокировок технологический bash context регулярные Богачев grep egrep awk gawk cat sed print printf echo sort logcfg
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
См. также
HighLoad оптимизация Разработчик 1С 8.3 1С:ERP Управление предприятием 2 Бесплатно (free)
Использование оператора «В» для полей или данных составного типа (например, Регистратор) может приводить к неочевидным проблемам.
10.11.2025 15936 ivanov660 48
HighLoad оптимизация Разработчик 1С:Предприятие 8 1C:ERP Бесплатно (free)
Приведем примеры использования различных в динамических списках и посмотрим, почему это плохо.
18.02.2025 16519 ivanov660 39
HighLoad оптимизация Системный администратор Разработчик 1C:ERP Бесплатно (free)
Не всегда индексирование с дополнительным упорядочиванием полезно.
04.02.2025 15161 ivanov660 21
HighLoad оптимизация Технологический журнал Системный администратор Разработчик Бесплатно (free)
Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.
24.06.2024 19167 ivanov660 13
HighLoad оптимизация Разработчик 1С:Предприятие 8 Бесплатно (free)
Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.
06.06.2024 25011 Evg-Lylyk 73
Технологический журнал Разработчик 1С:Предприятие 8 Бесплатно (free)
Шпаргалка по настройке технологического журнала.
27.04.2024 72542 kuzyara 9
HighLoad оптимизация Разработчик 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.
13.03.2024 14652 spyke 29
HighLoad оптимизация Разработчик 1С:Предприятие 8 Бесплатно (free)
Оказывается, в типовых конфигурациях 1С есть, что улучшить!
13.03.2024 17044 vasilev2015 22
Было бы здорово, если после каждого скрипта был бы приведен образец вывода его результата.
Иначе приходится либо выполнять этот вывод мысленно, либо повторять у себя. А данные для повторения есть не всегда..
Мне выгодно, чтобы Вы повторили у себя и если будут ошибки присылали. Буду признателен за любые замечания и предложения.
Не знаю, как другие, но я практически никогда не использую чужие скрипты в том виде, как они опубликованы. При этом всегда их изучаю, чтобы что-то подсмотренное перенять и применить в своей работе.
Вот здесь, например, мне интересно было каким образом Вы получили имя файла в строке для awk. Я вижу что его подставляет в начало каждой строки egrep. Но, в таком случае, контексты теперь уж точно обрезаются только до первой строки. По крайней мере, так мне сообщает мой "мысленный вывод результата". Уж у TLOCK-ов то контекст точно не однострочный. Или я не прав?
Кроме того, как я уже писал, для запуска скрипта в том виде, как он опубликован, нужны подходяще собранные логи. У меня, например, сейчас нет подходящих. Рыться в архивах? Ждать когда же вылезет какая-нибудь взаимоблокировка? Так они устранены давно уже. Моделировать специально для проверки скрипта? Всё это слишком трудозатратно, по крайней мере, пока нет реальной потребности решить проблему.
Насчет ошибок и отзывов: вот я почему-то думаю, что прямо сейчас, по прочтению статьи, вряд ли кто-то бросится запускать это у себя. Может быть отметят в избранное, чтобы вернуться когда понадобится. Поэтому фидбэка тут особо полезного не получить. А статья могла бы быть информативнее с примерами вывода. Но это конечно, лишь мое скромное мнение.
В моем ТЖ контекст только в TTimeout, TDeadlock одной строкой.
Файл настройки ТЖ обычный.
Скрипт кому-то пригодится. Буду ждать.
А вообще, интересно Вы с awk-ом работаете. Мне раньше не встречалось, чтобы разделители через "или" набирались.
И корова с тигром - забавно :)
Тоже оценил такую конструкцию, однако интересно сколько вычислительного времени расходуется на такой разбор ...
Не сочтите за придирку, но хотелось бы видеть немного комментариев в самом коде, хотя бы ссылающихся на пункты пояснений, которые приводятся до этого в статье. Вы используете \ для много строчных выражений. А это позволяет использовать комментарии прямо в скрипте:
printf '3e2' | \
# comment
egrep --only-matching '3'Таким образом код можно разделять на более читаемые логические блоки.
Иногда кстати можно услышать, что записанный в баше RegExp - это write only code. Потому что никому кроме автора редактировать не удаётся. Но такой ситуации можно избежать, если снабжать отдельные строки комментариями прямо в коде. Ведь передавать такой код например коллеге удобнее без дополнительных ссылок на статьи ))
Планируете ли Вы ещё писать на эту тему? Очень интересные приёмы демонстрируете.
Про комментарии в коде думал, но есть нюансы:
1. Хотелось однообразия, а после каждой строки не получилось.
Например, awk разбит на несколько строк - внутри не поставить #
2. На stackoverflow нет комментариев после каждой строки
3. Если скрипт потеряет связь со статьей - для меня скорее недостаток
Поэтому я сделал коммернтарии для каждой строки, но поместил их после
И выполнил проверку кода конфигурации.
Нашёл множество ошибок.
И хотел этот массив обработать быстро и наглядно.
Не писали парсер, который так сделает?
Обновление я уже поставил на рабочую базу. И ошибки исправлены.
Но хотелось бы иметь такой инструмент.
в статье
парсер для файла ОтчетОСравнении.txt сравнения конфигураций.
если логи 1С - технологический журнал...
то его сначала включить надо... аккуратно иначе логи не 3 Гб будут а 300 Гб
если логи - это лог тех.журнала 1С сервера... то про какую версию это всё?
8.3.XX разные тем более 8.2 и 8.3 вообще
и ещё увидел во 2-ом скрипте ссылку на логи 2003 года?! это вы так "пошутили"?
--include "200311*.log"
я лично (да думаю и многие 1С-программисты) не очень то любят лезть в тех.журнал,
тем более анализировать его через BASH-команды... т.е. практически руками...
есть прекрасные инструменты и в 1С... и всякие внешние обработки и публикации
зачем ещё один "велосипед"... Вы конечно молодец, и так можно (если умеючи)
Ещё "комментарий"! - не все блокировки (взаимоблокировки DeadLock) отражаются в тех.журнале как прямо "блокировки"...
есть "ошибки" ERROR ... которые показываются пользователям как ошибка блокировки объекта...
или ошибка совместного доступа и т.д.
это те ошибка, которые можно "увидеть" в Журнале регистрации в 1С...
а некоторые блокировки вообще не поймать... без SQL-логов
я лично считаю, что "лучший" инструмент анализа тех.журнала у группы Гилёва gilev.ru
и бесплатный и легко "включаемый" - само всё анализируется... автоматически
и блокировок
и взаимо-блокировки
и долгие запросы -
и анализ Журнала регистрации
есть прекрасные статьи и видео от Андрея Бурмистрова... выступления на ИнфоСтарт - 2014, 2015, 2016г.
статьи от Андрея Бурмистрова
"Ускорение в 100 раз. Решаем проблему блокировок
Опять упало
система автоматизации анализа ошибок, связанных со скоростью работы 1С
ещё статьи
Ловля блокировок на связке "Microsoft SQL server - 1С"
В статье указано, что анализируем технологический журнал.
Предполагается, что читатель умеет настраивать ТЖ.
Для начинающих есть более подробная статья
Тестировал на платформе 8.3.12, должно работать на (почти)всех платформах.
200311 - значит, 20 год, месяц 03.
Не знаю, что любят 1С-программисты, а разработчики сервисов
точно не любят делиться своими достижениями и открывать код.
Но мы теперь знаем, что сервис (deadlock) можно заменить на десять строчек кода.
Открыто, для всех.
Это позволит исправить скрипт.
awk: warning: escape sequence `\/' treated as plain `/'
awk: cmd. line:4: warning: escape sequence `\.' treated as plain `.'
В чем может быть проблема при запуске этого:
#!/bin/bash
egrep '^[0-9][0-9].{10,24},TLOCK,.*WaitConnections=[0-9]' -H -R --include "200311*.log" \
| awk -F'(^.{1,20}\/)|(.log:)|(:.{8,21},TLOCK,.*t:connectID=)|(,SessionID=.*,Regions=)|(,Locks=.*,WaitConnections=)|((,connectionID=)|(,Context=))' \
'BEGIN {print "#!/bin/bash" > "2step.sh"} \
{gsub("'\''",".",$5) \
; ord[$3,$5,$4]="Time"$3"Regions"$5"Tiger"$6"EndOrder" \
; cow[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TLOCK.*t:connectID="$4".*,Regions="$5".*WaitConnections="$6"'\'' -h -R --include "$2".log" \
; tiger[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TLOCK.*t:connectID="$6".*,Regions="$5".*WaitConnections=,'\'' -h -R --include "$2".log" \
; deadlock[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TDEADLOCK.*t:connectID="$4".*DeadlockConnectionIntersections=."$4"."$6"'\'' -h -R --include "$2".log" \
; timeout[$3,$5,$4]="egrep '\''^"$3"\.{10,25},TTIMEOUT.*t:connectID="$4".*WaitConnections="$6"'\'' -h -R --include "$2".log";} \
END {for (K in ord) \
{print ord[K]cow[K]"\n"ord[K]timeout[K]"\n"ord[K]deadlock[K]"\n"ord[K]tiger[K]"\n"ord[K]"echo "; }}' \
| sort -rnb \
| awk -F'^.*EndOrder' '{print $2;}' >> "2step.sh" \
; ./2step.sh >> "result.txt"
это не проблема, а предупреждение что последовательность символов рассматривается как косая и точка.
Внутри AWK "крутится" цикл.
переменные $1...$6 - это значения колонок для каждой строки.
ord[..] - это многомерный массив.
Скрипт обрабатывает содержимое файлов по маске 200311*.log
к bash нужно привыкнуть, он необычный.
Почитайте описание скрипта, посмотрите как работает AWK.
$ ./2step.sh
-h -R --include 00:01.302128-74,TLOCK,4,process=rphost,p:processName=kb_erp,OSThread=11012,t:clientID=4997,t:applicationName=BackgroundJob,t:computerName=NBCS0009,t:connectID=4547.log
.*,Regions=a210b08c-a809-462a-8619-f61ed201d8ff.*WaitConnections=,: Слишком длинное имя файла
-h -R --include 00:01.302128-74,TLOCK,4,process=rphost,p:processName=kb_erp,OSThread=11012,t:clientID=4997,t:applicationName=BackgroundJob,t:computerName=NBCS0009,t:connectID=4547.log
: Слишком длинное имя файла25,TDEADLOCK.*t:connectID=4546.*DeadlockConnectionIntersections=.4546.
начало файла выглядит так:
#!/bin/bash
egrep '^Reference84.REFLOCK\.{10,25},TTIMEOUT.*t:connectID=4546.*WaitConnections='
' -h -R --include 00:01.302128-74,TLOCK,4,process=rphost,p:processName=kb_erp,OSThread=11012,t:clientID=4997,t:applicationName=BackgroundJob,t:computerName=NBCS0009,t:connectID=4547.log
egrep '^Reference84.REFLOCK\.{10,25},TLOCK.*t:connectID='
.*,Regions=a210b08c-a809-462a-8619-f61ed201d8ff.*WaitConnections=,' -h -R --include 00:01.302128-74,TLOCK,4,process=rphost,p:processName=kb_erp,OSThread=11012,t:clientID=4997,t:applicationName=BackgroundJob,t:computerName=NBCS0009,t:connectID=4547.log
egrep '^Reference84.REFLOCK\.{10,25},TLOCK.*t:connectID=4546.*,Regions=a210b08c-a809-462a-8619-f61ed201d8ff.*WaitConnections='
' -h -R --include 00:01.302128-74,TLOCK,4,process=rphost,p:processName=kb_erp,OSThread=11012,t:clientID=4997,t:applicationName=BackgroundJob,t:computerName=NBCS0009,t:connectID=4547.log
egrep '^Reference84.REFLOCK\.{10,25},TDEADLOCK.*t:connectID=4546.*DeadlockConnectionIntersections=.4546.'
' -h -R --include 00:01.302128-74,TLOCK,4,process=rphost,p:processName=kb_erp,OSThread=11012,t:clientID=4997,t:applicationName=BackgroundJob,t:computerName=NBCS0009,t:connectID=4547.log
echo ПоказатьНо просто как учил Богачев истинную причину таймаута трудно найти - TLOCK ставится платформой в обработке проведения при записи движений документа, сразу по 10 измерениям, то есть гранулярность отличная. Но запись конкретно в этот блокируемый регистр занимает миллисекунды, и записано очень мало строк. Похоже это всё обернуто дополнительной транзакцией длительных фоновых операций и задержку дает другой регистр. Получается надо шерстить по событиям всех регистров движений
В общем случае методика следующая:
1. Смотрим TTIMEOUT из него понимаем на какой таблице было ожидание, и какой connectID был виновником НАЧАЛА ожидания;
2. Смотрим по connectID виновника события SDBL фиксации или отмены транзакции, которая началось ранее или одновременно по отношению к нашему событию таймаута и закончилось позже начала нашего таймаута/тлока. И вот тут самое интересно что позже начала, а не позже окончания.
Тут-то и кроется основное расстройство для таких "анализаторов" как я. Я то ждал по молодости, что виновник удерживал блокировку все 20 секунд, но на практике часто тут получается цепочка ожиданий из которых в ТЖ виден только первый виновник. (Например, пытаемся заблокировать остатки по 2-м товарам и попадаем на ожидание от сеанса 1, который держит блокировку по первому товару 15 секунд. На 10-й секунде ещё сеанс 2 устанавливает блокировку по товару 2 тоже на 15 секунд.
В итоге мы видим таймаут в ТЖ, где виновник сеанс 1 и по sdbl понимаем, что он отпустил конфликтный ресурс ранее, чем мы словили таймаут). И чтобы найти других виновников необходимо вычислить по tlock'ам сеансы, которые блокировали конфликтный ресурс по пересекающемуся пространству не позже, чем завершилась транзакция сеанса 1. И в цепочке в общем случае может быть несколько таких виновников.
Чтобы это провернуть необходимо собирать в ТЖ как минимум все таймауты без ограничения по времени установки (так как виновник мог установить её мгновенно), а так же необходимо собирать поля блокировки для tlock'ов (эти 2 настройки могут приводить к очень большим файлам логов на нагруженных системах). Ну и ещё найти пересечение пространств у двух tlock'ов технически не так уж и просто (хотя если по этому пространству немного потенциальных виновников, то можно скинуть в один файл и найти глазами).
То есть иными словами - иногда связь между проблемой и его источником проще и быстрее найти через конфигуратор, а не через события ТЖ.
Команда в bash egrep '^.{20,30},TLOCK,.*WaitConnections=[0-9]' -H -R --include "23041207.log" при считывании одного файла на 36Мб висит бесконечно долго, с загрузкой ЦП на 100% и ничего не выводит... При этом, есть файлы из этого же часа большего и меньшего размера, которые считываются нормально... Ситуация повторяется на 2х компьютерах... logcfg стандартный. Не сталкивались с таким?
Надеюсь, у вас журнал событий полный (все поля событий).
При выполнении bash скрипта сделайте отладку - смотрите результат выполнения от простого к сложному, от строки к строке.
Не удается разобраться самостоятельно - присылайте (фрагмент) ТЖ, я проверю.
Или можете просто написать, что разбираться неохота, но скрипт плохой ))
Спасибо за обращение. Слушал ваши курсы (как и все другие курсы по теме).
Алгоритм проходит файлы ТЖ два раза: первый раз выбирает события с ненулевыми ожиданиями и составляет на основе них шаблоны, а второй раз по шаблонам ищет все строки, участвующие в блокировке (жертву и виновника).
Шаблон для поиска egrep имеет простой вид например, *t:connectID="$4".*,Regions="$5".*WaitConnections="$6" переменные подстановки $4, $5, $6 - это фрагменты из события с ненулевым ожиданием.
Скорость работы алгоритма линейная, 10 Гб обрабатывает около 1 минуты.
Если содержимое Regions виновника совпадает с содержимым Regions жертвы, то строки будут найдены.
Если есть разумный алгоритм поиска, то шаблоны можно поменять.
Пришлите фрагменты ТЖ для более подробного ответа
P.S. Мне кажется, сейчас акцент делают на Elastic, bash отдыхает ?
В ТЖ есть запись -
04:18.792002-0,TDEADLOCK,5,level=INFO,process=rphost,p:processName=demo_expert,OSThread=41664,t:clientID=1516,t:applicationName=1CV8C,t:computerName=msi,t:connectID=366,SessionID=25,Usr=Администратор_ТЦ000002,AppID=1CV8C,DBMS=DBPOSTGRS,DataBase=localhost\demo_expert,DeadlockConnectionIntersections='366 368 AccumRg505.DIMS Exclusive Fld2683=0 Fld506=19:8634001d600d9ad211deea23b1edc215 Fld507=16:b1a2bcaec5b8981a11e4b68056da7475 Fld508=18:acd3005056c0000811e2cea62aeec8ba Period=[T"20240601000000":+],368 366 AccRg3942.DIMS Exclusive Account=3930:9e14bcaec5d979f011e32696603effaf Correspond=0 ExtDimension1=15:896ce0cb4ed5f65511e4a2d5a2eb6c99 ExtDimension2=16:b1a2bcaec5b8981a11e4b68056da7475 ExtDimension3=18:acd3005056c0000811e2cea62aeec8a5 Fld2683=0 Fld3943=19:8634001d600d9ad211deea23b1edc215 Fld3944=Null Period=[T"20240601000000":+] Splitter=0',Context='Форма.Вызов : Обработка.ТЦПродажа.Форма.ТЦФорма.Модуль.СоздатьДокументКопированием
Обработка.ТЦПродажа.Форма.ТЦФорма.Форма : 47 : ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);'- Две разные пары блокировок в DeadlockConnectionIntersections!
В таком случае - нужно анализировать оба региона (AccumRg505.DIMS и AccRg3942.DIMS) по TLOCK или достаточно 1?
(Согласен - вопрос выглядит (как минимум у меня!) глупо - указаны же разные, а => у меня однозначно напрашивается и анализ по обеим регионам, но -
где я находил примеры - везде были только пары с 1 регионом! 1 жертва и 1 виновник - по 1 региону!)
Поэтому и просьба - покажите пожалуйста алгоритм (последовательность скриптов) расследования в таком случае.
Хотя и - вроде как при взаимоблокировке - жертва и виновник - по одному выбирается 1с.
И...
А ведь это - из учебной базы от Антона Евтушенко (на курсе "Применение методик..."), но - после курса (в прошлом году проходил) - теперь я и не знаю - как у него спросить!
Вот и - только об стенку бьюсь!!
(И да - Андрея Бурмистрова я спросил в личке - надеюсь поможет/подскажет.)
> Если содержимое Regions виновника совпадает с содержимым Regions жертвы, то строки будут найдены.
В таком случае если в Regions содержит несколько разных значений, то анализ не будет корректным.
Допустим если у TLOCK жертвы указано несколько разных пространств блокировки через запятую, а у TLOCK виновника только одно пространство, тогда нельзя "в лоб" сравнивать просто 2 значения Regions.
Нужно Regions жертвы разбивать на составные части и каждое значение искать отдельно и при этом помнить что у виновника тоже может быть несколько значений в Regions.
P.S.
Не знаю кто на чем делает акцент, знаю что универсального решения нет, каждый свое использует в зависимости от условий и задач.
Если вы внешний эксперт и СБ лютуюет, это одна история, вот там bash может быть оправдан, но это далеко не самый частый сценарий. И даже там обычно можно договорится и поставить инструменты подписав определенное соглашение. Проект закончится, и чем потом будут пользоваться штатные программисты? А если нужны отчеты по проблемам, а анализ дедлоков и ожиданий на СУБД, а анализ ошибок с автоматической разбивкой на категории, а если новые свойства нужно добавить в ТЖ и т.д.? Не факт что штатные программисты смогут это потянуть скриптами, а на каждый чих звать эксперта ну такое.
Для меня скрипты это как скальпель, нужны для тонкой не типовой работы, а для типовых задач уже давно придуманы и написаны гораздо более удобные инструменты. Удобные не только экспертам, а в том числе и разработчикам.
ELK конечно удобно, но очень уж требовательно к ресурсам.
На мой взгляд для большинства подойдут спец. инструменты, с удобным интерфейсом, отчетами на СКД и пр. тем более есть и бесплатные. Даже в бесплатных ИнструментахРазработчика есть достаточно всякого для анализа. Тут на вкус и цвет...
Если очень хочется собрать свой велосипед, то наиболее оптимальным мне кажется Vector + ClickHouse. Туда можно и логи тж грузить и журнал регистрации, жмется все очень хорошо и работает быстро. Запросы строите всем знакомым SQL, да и интерфейсов куча всяко-разных и вроде как можно как внешний источник к 1С прикрутить. Конечно придется немного повозится с настройками, зато потом пользоваться этим очень удобно.
Виновник, блокировавший регион Б не будет найден.
Потому что в шаблоне после региона стоит точка звездочка - любые символы.
Ок, спасибо, именно это и хотел выяснить.
Вы писали про замечания и предложения, вот и решил написать :)
Еще есть момент когда значения полей в Locks могут содержать перенос строки, т.е. свойство Locks может быть многострочным, кажется в текущей реализации скрипт это тоже не учитывает.
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 1213872
Создание 20.03.20 16:30
Обновление 26.07.22 19:59
Просмотры 19306
Загрузки 0
Рейтинг
93
Комментарии 53
Код открыт Да
Рубрики HighLoad оптимизация Технологический журнал
Кому
Системный администратор
,
Разработчик
Тип файла Нет файла
Платформа 1С:Предприятие 8
Конфигурация Универсальные
Операционная система Не имеет значения
Страна Не имеет значения
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Бесплатно (free)