Monitorar SQLs que geram Locks no Oracle
Autor: Hudson Santos | Publicado: 2012-02-29T07:46:00-08:00

Essa semana eu precisei monitorar alguns locks que estavam ocorrendo em uma base de produção.
Só que os locks eram&nbsp;esporádicos, não dava para ficar na frente de uma tela de OEM esperando acontecer, além disso eu precisava descobrir o SQL que estava bloqueando algum recurso e o SQL que estava esperando pelo recurso.

Eu criei um job que roda de 2 em 2 minutos , ele verifica se existe alguma sessão com evento de espera tipo o :&nbsp;enq: TX - row lock contention.
Caso exista e o tempo de espera seja maior que X ele loga os SQLSs que estao bloqueando e esperando por um recurso,o SID das sessões,a data e o tempo de espera da sessão em uma tabela que criei para isso.

O Mais legal nisso foi que descobri a coluna&nbsp;Prev_sql_id da V$SESSION, com ela conseguimos saber o SQL que esta bloqueando algum recurso.

Abaixo segue o comando de criação do JOB e da Tabela para logar.

UPDATE:
&nbsp;Legal olhar um post de quase 4 anos atrás, vendo agora não gosto muito desse código, então decide realizar algumas pequenas modificações , graças ao comentário do Mauro rafael, modifiquei na hora mesmo, só por capricho,rs.

Tabela:

CREATE TABLE LOG_LOCK (SQL_BLOCKER VARCHAR2(1000),SID_BLOCKER INT, SQL_BLOCKED VARCHAR2(1000),SID_BLOCKED INT,DATA_LOG DATE,WAIT INT);Job:BEGIN&nbsp; DBMS_SCHEDULER.create_job (&nbsp;job_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 'Monitor_Lock',&nbsp;job_type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 'PLSQL_BLOCK',&nbsp;job_action&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 'DECLAREV_BLOCKER INT;V_BLOCKED INT;V_SQL VARCHAR2(1000);V_SQL2 VARCHAR2(1000);V_TIME INT;V_CTR INT;BEGIN&nbsp;&nbsp;&nbsp; SELECT COUNT(*) INTO V_CTR&nbsp;&nbsp;&nbsp; FROM v$session s&nbsp;&nbsp;&nbsp; WHERE event LIKE ''enq: %'';&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FOR CRS IN (select s1.sid BLOCKER, s2.sid BLOCKED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from v$lock l1, v$session s1, v$lock l2, v$session s2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where s1.sid=l1.sid and s2.sid=l2.sid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and l1.BLOCK=1 and l2.request &gt; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and l1.id1 = l2.id1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and l2.id2 = l2.id2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LOOP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IF V_CTR &gt;= 1 THEN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; V_BLOCKED:=CRS.BLOCKED;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; V_BLOCKER:=CRS.BLOCKER;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT SQL_TEXT INTO V_SQL FROM V$SQL S&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INNER JOIN V$SESSION V ON (V.Prev_sql_id=S.SQL_ID)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE V.SID=V_BLOCKER;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT SQL_TEXT ,V.SECONDS_IN_WAIT INTO V_SQL2,V_TIME FROM V$SQL S&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INNER JOIN V$SESSION V ON (V.sql_id=S.SQL_ID)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE V.SID=V_BLOCKED;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IF V_TIME &gt; 30 THEN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT INTO LOG_LOCK (SID_BLOCKER,SQL_BLOCKER,SID_BLOCKED,SQL_BLOCKED,DATA_LOG,WAIT) VALUES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (V_BLOCKER,V_SQL,V_BLOCKED,V_SQL2,SYSDATE,V_TIME);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMMIT;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END IF;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END IF;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END LOOP;END;&nbsp;',&nbsp;start_date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; trunc(sysdate)+18/24,&nbsp;repeat_interval =&gt; 'FREQ=MINUTELY;INTERVAL=2',&nbsp;end_date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; NULL,&nbsp;enabled&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; TRUE,&nbsp;comments&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 'Job defined entirely by the CREATE JOB procedure.');END;/