При закрытии подписчики были переданы в рассылку "СУБД Oracle "с нуля"" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
| Информационный Канал Subscribe.Ru |
Уважаемые подписчики рассылки!
Не так давно мне пришло письмо с вопросом о том, как контролировать задания
(jobs) в Oracle. Вот почему в этом выпуске я решил представить перевод ответа
Тома Кайта на давно заданный
аналогичный вопрос... Кроме того, я хочу представить вам новую книгу, над
переводом которой я сейчас работаю.
Как понять, что реально делает задание? Я хотел бы получать признаки жизни от посланного на выполнение 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 --------------------------
Он показывает:
Может иметь смысл использовать пакет DBMS_APPLICATION_INFO для задания значений столбцов action, client_info и module в представлении v$session - после этого при выполнении сценария showsql вы будете получать значения из этих столбцов, что поможет понять, на каком эхтапе выполнения сейчас находится программа.
Том,
я попытался использовать твой сценарий, но столкнулся с проблемой при
использовании его совместно с 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.
Оригинал обсуждения этого вопроса можно найти здесь. Я не переводил часть, не относящуюся непосредственно к использованию нескольких индексов для выполнения запроса.
Copyright © 2004 Oracle Corporation
Все вышедшие выпуски рассылки можно найти на сайте рассылки. Там же реализована возможность поиска материалов по ключевым словам (с помощью Google...)
Уважаемые подписчики. Занялся я переводом очередной хорошей книги по СУБД Oracle, Mastering Oracle PL/SQL: Practical Solutions. Том Кайт ее рекомендовал (и рецензировал). Не зря, кстати. С разрешения издательства я собираюсь опубликовать в рассылке фрагменты перевода. Вам это интересно? Пишите...
Краткое содержание:
С наилучшими пожеланиями,
В.К.
| http://subscribe.ru/
E-mail: ask@subscribe.ru | Отписаться |
| В избранное | ||