Мониторинг заданий

Источник: ln

Как понять, что реально делает задание? Я хотел бы получать признаки жизни от посланного на выполнение SQL-оператора. Не видно никаких блокировок, которые мешали бы ему работать - я работаю на новом и практически не используемом сервере. Этот сервер должен заменить текущий производтсвенный, поэтому я, по сути, скопировал все настройки. Пришлось внести несколько изменений в файл INIT.ORA, в основном, связанных с изменением каталогов: ранее значение compatible было 7.3.2.3.0, а теперь - 7.3.4.5.0; ресурсов enqueue было 16000, а теперь - 32000 (я просто выполнил "diff" для двух файлов). Я уверен, что никаких блокировок не может быть, но ЧТО делает задание, мне непонятно.

Я пытался просматривать все обнаруженные представления динамической производительности V$; где взять их полный список? В одной из книг, которую я читал, написано, что надо обращаться к представлению X$KQFVI, но его, похоже, нет...

Ответ Тома Кайта

Чтобы узнать, какие задания сейчас выполняются, используйте следующее представление:

ops$tkyte@8i> desc dba_jobs_running
 Name                          Null?    Type
 ----------------------------- -------- --------------------
 SID                                    NUMBER
 JOB                                    NUMBER
 FAILURES                               NUMBER
 LAST_DATE                              DATE
 LAST_SEC                               VARCHAR2(8)
 THIS_DATE                              DATE
 THIS_SEC                               VARCHAR2(8)
 INSTANCE                               NUMBER

Чтобы узнать, какой sql-оператор выполняет задание, и выполняет ли оно что-то вообще, можно использовать такой сценарий sqlplus:

------ begin of showsql.sql --------------------------

column status format a10
set feedback off
set serveroutput on
select username, sid, serial#, process, status
from v$session
where username is not null
/
column username format a20
column sql_text format a55 word_wrapped
set serveroutput on size 1000000
declare
    x number;
begin
    for x in
    ( select username//'('//sid//','//serial#//
                ') ospid = ' //  process //
                ' program = ' // program username,
             to_char(LOGON_TIME,' Day HH24:MI') logon_time,
             to_char(sysdate,' Day HH24:MI') current_time,
             sql_address, LAST_CALL_ET
        from v$session
       where status = 'ACTIVE'
         and rawtohex(sql_address) <> '00'
         and username is not null order by last_call_et )
    loop
        for y in ( select max(decode(piece,0,sql_text,null)) //
                          max(decode(piece,1,sql_text,null)) //
                          max(decode(piece,2,sql_text,null)) //
                          max(decode(piece,3,sql_text,null))
                               sql_text
                     from v$sqltext_with_newlines
                    where address = x.sql_address
                      and piece < 4)
        loop
            if ( y.sql_text not like '%listener.get_cmd%' and
                 y.sql_text not like '%RAWTOHEX(SQL_ADDRESS)%')
            then
                dbms_output.put_line( '--------------------' );
                dbms_output.put_line( x.username );
                dbms_output.put_line( x.logon_time // ' ' //
                                      x.current_time//
                                      ' last et = ' //
                                      x.LAST_CALL_ET);
                dbms_output.put_line(
                          substr( y.sql_text, 1, 250 ) );
            end if;
        end loop;
    end loop;
end;
/
column username format a15 word_wrapped
column module format a15 word_wrapped
column action format a15 word_wrapped
column client_info format a30 word_wrapped
select username//'('//sid//','//serial#//')' username,
       module,
       action,
       client_info
from v$session
where module//action//client_info is not null;

------------------------ eof --------------------------

Он показывает:

  • кто зарегистрирован;
  • если сеансы активны, какой sql-оператор они выполняют;
  • сколько времени они это делают (столбец last_call_et)

Может иметь смысл использовать пакет DBMS_APPLICATION_INFO для задания значений столбцов action, client_info и module в представлении v$session - после этого при выполнении сценария showsql вы будете получать значения из этих столбцов, что поможет понять, на каком этапе выполнения сейчас находится программа.

Не могу получить текст SQL. Комментарий читателя от═22 июня 2004 года

Том,

я попытался использовать твой сценарий, но столкнулся с проблемой при использовании его совместно с FGA (Fine Grained Auditing). Вот мой сценарий:

exec DBMS_FGA.ADD_POLICY(OBJECT_SCHEMA    => 'DEMO',OBJECT_NAME    =>
'REF_UR',POLICY_NAME    => 'POL_REF_UR',HANDLER_SCHEMA    =>
'DEMO',HANDLER_MODULE=> 'CAPTURE',ENABLE =>  TRUE)

А вот и процедура Capture:

CREATE OR REPLACE procedure CAPTURE_FGA(V_SCHEMA VARCHAR2,V_TABLE
VARCHAR2,V_POLICY VARCHAR2)
AS
    x number;
    scenario number;
    testsq varchar2(4000);

begin

    for x in
    ( select username//'('//sid//','//serial#//
                ') ospid = ' // process //
                ' program = ' // program, username,
             to_char(LOGON_TIME,' Day YYYY-MM-DD HH24:MI:SS') logon_time ,
             to_char(sysdate,' Day YYYY-MM-DD HH24:MI:SS') current_time,
sql_address,prev_sql_addr,LAST_CALL_ET,MACHINE,TERMINAL,process,program,
audsid,sid,serial#,osuser,a.module,b.CPU_TIME,b.EXECUTIONS,b.FETCHES,b.INVALIDATIONS, b.LOADS,
b.OPTIMIZER_COST,b.OPTIMIZER_MODE,b.sorts,b.OPEN_VERSIONS,b.ROWS_PROCESSED,
b.BUFFER_GETS,b.DISK_READS,b.PARSE_CALLS,b.ELAPSED_TIME,b.USERS_EXECUTING,b.USERS_OPENING,
b.LOADED_VERSIONS,b.FIRST_LOAD_TIME,b.LAST_LOAD_TIME
        from v$session a,v$sql b
        where status = 'ACTIVE'
        and rawtohex(prev_sql_addr) <> '00'
        and b.address = prev_sql_addr
        and username is not null order by last_call_et)
     loop
        for y in ( select max(decode(piece,0,sql_text,null)) //
                          max(decode(piece,1,sql_text,null)) //
                          max(decode(piece,2,sql_text,null)) //
                          max(decode(piece,3,sql_text,null))
                          sql_text
                     from v$sqltext_with_newlines
                     where
                     piece < 4
                     --and address =x.sql_address
                     and address in
                     (select prev_sql_addr from v$session
                     where sid = 18
                     and serial# = 475)
                     )
       loop
            if ( y.sql_text not like '%listener.get_cmd%' and
                 y.sql_text not like '%rawtohex(sql_addresse)%' )
            then
                insert into rt_suivi_consult_aas
(trc_schema,trc_table,trc_policy,dt_trace,sql_text_line,terminal,
machine,username,process,program,sid,serial#,osuser,module,logon_time,
CPU_TIME,EXECUTIONS,FETCHES,INVALIDATIONS,LOADS,OPTIMIZER_COST,OPTIMIZER_MODE,
sorts,OPEN_VERSIONS,ROWS_PROCESSED,BUFFER_GETS,DISK_READS,PARSE_CALLS,ELAPSED_TIME,
USERS_EXECUTING,USERS_OPENING,LOADED_VERSIONS,FIRST_LOAD_TIME,LAST_LOAD_TIME)
                values
(v_schema,v_table,v_policy,x.current_time,y.sql_text,x.terminal,
x.machine,x.username,x.process,x.program,x.sid,x.serial#,x.osuser,
x.module,x.logon_time,x.cpu_time,x.EXECUTIONS,x.FETCHES,x.INVALIDATIONS,
                x.LOADS,x.OPTIMIZER_COST,x.OPTIMIZER_MODE,
                x.sorts,x.OPEN_VERSIONS,x.ROWS_PROCESSED,
                x.BUFFER_GETS,x.DISK_READS,x.PARSE_CALLS,
                x.ELAPSED_TIME,x.USERS_EXECUTING,x.USERS_OPENING,
                x.LOADED_VERSIONS,x.FIRST_LOAD_TIME,x.LAST_LOAD_TIME);
            end if;
        end loop;
    end loop;
end;
/

Затем, я выполняю

select * from ref_ur

и обращаюсь к таблице rt_suivi_consult_aas, чтобы проверить, перехвачен ли текст SQL-оператора, оказывается, что там следующий текст:

select max(decode(piece,0,sql_text,null)) //
                          max(decode(piece,1,sql_text,null)) //
                          max(decode(piece,2,sql_text,null)) //
                          max(decode(piece,3,sql_text,null))
                          sql_text

а не "select * from ref_ur"

Не подскажешь, в чем дело?

Ответ Тома Кайта

Пакет dbms_fga уже ЗАХВАТИЛ текст SQL-оператора - он уже в журнале аудита (audit trail). Всё уже сделано, просто выкиньте ваш код. Именно это и делает пакет dbms_fga.


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=23353