Hanganalyzer

 

Каждый DBA рано или поздно сталкивается с необходимостью определить, кто же сейчас блокирует того возмущенного пользователя, который ему названивает.

Есть несколько способов увидеть блокировки в базе. К примеру, на metalink'е можно прочитать хорошую заметку (Note:15476.1), под названием FAQ about Detecting and Resolving Locking Conflicts, в которой приведены несколько методов обнаружения блокировок.

Один из простых и проверенных способов -- скрипт $ORACLE_HOME/rdbms/admin/utllockt.sql Он показывает блокировки в виде дерева. Вот пример его работы:

WAITING_SESSION   TYPE MODE REQUESTED    MODE HELD         LOCK ID1 LOCK ID2
----------------- ---- ----------------- ----------------- -------- --------
8                 NONE None              None              0         0
   9              TX   Share (S)         Exclusive (X)     65547     16
      7           RW   Exclusive (X)     S/Row-X (SSX)     33554440  2
      10          RW   Exclusive (X)     S/Row-X (SSX)     33554440  2

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

А ещё бывают такие блокировки, которые не показываются этим скриптом. Вот пример:
В одной сессии делаем так:

create or replace procedure called1 is begin null; end;
/
begin
called1;
dbms_lock.sleep(1000);
end;
/

А во второй сессии сессии пытаемся выдать grant на called1:

grant execute on called1 to system;

Вторая сессия будет ждать, пока не завершится анонимный блок в первой сессии, пытаясь получить 'library cache pin'. Подобное же будет происходить при попытке перекомпиляции called1.

Довольно часто такие ситуации возникают на базе, где работают девелоперы. Нельзя, используя utllockt.sql или выборку из v$lock, увидеть такую блокировку. Можно понять, кто держит объект, если сделать выборку из v$access.

Но, оказывается, есть единый способ увидеть любые блокировки в базе. Это event hanganalyze, доступный с версии 8.1.6. Подробнее об этом можно почитать в Note:215858.1 на metalink'е.

Если вкратце, то при выполнении команды

alter session set events 'immediate trace name hanganalyze level 2';

в {user_dump_dest} сформируется trace файл, который будет содержать краткую информацию о всех сессиях и их взаимоотношениях.

Отдельно хочется подчеркнуть, что при выполнении event'а hanganalyze тратится примерно в пять раз меньше ресурсов базы (измерялось с помощью runstats), чем при выполнении utllockt.sql. А если учесть, что есть блокировки, которые не показывает utllockt.sql, то этот метод (hanganalyze) предстает в ещё более привлекательном свете.

Trace файл, полученный от hanganalyze, можно рассматривать вручную (используя сведения из Note:215858.1), а можно воспользоваться моим скриптом hanganalyze.py, который сам создаст нужный trace файл и тут же обработает его, показав в древовидном виде [sid, serial#] зависимость сессий.

Скрипт написан на языке python. В скором времени я выложу бинарные версии этого скрипта для стандартной тройки операционных систем (Windows/Linux/Solaris).

Вот краткий help, полученный в результате выполнения 'hanganalyze.py -h':

hanganalyze.py v1.1.1.1, (c) 2005 Egor Starostin
usage: hanganalyze.py [-f tracefile.trc] [-h] [-k]
  -f specify tracefile to parse
  -h this screen
  -k keep trace file in {user_dump_dest} directory

 

Если у Вас возникли вопросы или замечания по скрипту hanganalyze.py, то Вы всегда можете их написать мне.