Как узнать, какой пакет/процедура обновляет таблицу?

Я хотел бы узнать, возможно ли узнать, какой пакет или процедура в пакете обновляют таблицу?

Из-за определенного передаваемого проекта (человек, который передал проект, с тех пор уехал) без необходимой документации, данные, что мы знаем, что обновляли всегда, возвращаются к некоторой странной исходной точке.

Мы предполагаем, что это могло быть заданием базы данных или планировщиком, который выполняет команду обновления без нашего ведома. Я надеюсь, что существует способ узнать, откуда исходный код звонит этого, обновляет таблицу и вставляет источник как триггер на той таблице, которую мы контролируем.

Какие-либо идеи?

Спасибо.

6
задан N2EE 5 January 2010 в 01:37
поделиться

2 ответа

UPDATE: Я прокололся и выяснил. как отследить заявление до его владеющий объектом PL/SQL.

В сочетании с тем, что упомянул Тони, вы можете создать таблицу протоколирования и триггер, который выглядит следующим образом:

CREATE TABLE statement_tracker
( SID NUMBER
, serial# NUMBER
, date_run DATE
, program VARCHAR2(48) null
, module VARCHAR2(48) null
, machine VARCHAR2(64) null
, osuser VARCHAR2(30) null
, sql_text CLOB null
, program_id number
);

CREATE OR REPLACE TRIGGER smb_t_t
   AFTER UPDATE
   ON smb_test
BEGIN
   INSERT 
     INTO statement_tracker
   SELECT ss.SID
        , ss.serial#
        , sysdate
        , ss.program
        , ss.module
        , ss.machine
        , ss.osuser
        , sq.sql_fulltext
        , sq.program_id
     FROM v$session ss
        , v$sql sq
    WHERE ss.sql_address = sq.address
      AND ss.SID = USERENV('sid');
END;
/

Для того, чтобы триггер был скомпилирован выше, вам нужно предоставить владельцу триггера эти права, когда вы входите в систему как пользователь SYS:

grant select on V_$SESSION to <user>;
grant select on V_$SQL to <user>;

Скорее всего, вы захотите защитить оператор вставки в триггер с каким-то условием, которое заставляет его протоколировать только тогда, когда происходит интересующее вас изменение - на моем тестовом сервере этот оператор запускается довольно медленно (1 секунда), поэтому я не хотел бы протоколировать все эти обновления. Конечно, в таком случае вам нужно будет изменить триггер на row-уровень, чтобы вы могли проверять :new или :old значения. Если вас действительно беспокоят накладные расходы select, вы можете изменить его, чтобы не присоединяться к v$sql, а вместо этого просто сохранить колонку SQL_ADDRESS, затем запланировать работу с СУБД_JOB, чтобы она отключилась и обновила колонку sql_text вторым оператором обновления, тем самым выгрузив обновление в другой сеанс и не блокируя ваше первоначальное обновление.

К сожалению, это расскажет вам только половину истории. Оператор, который вы увидите в журнале, будет самым проксимальным оператором - в данном случае, обновление - даже если оригинальный оператор, выполняемый инициировавшим его процессом, является хранимой процедурой. В этом случае вводится столбец program_id. Если оператор обновления является частью процедуры или триггера, то program_id будет указывать на object_id рассматриваемого кода - вы можете решить это следующим образом:

SELECT * FROM all_objects where object_id = <program_id>;

В случае, когда оператор обновления выполнялся непосредственно от клиента, я не знаю, что представляет собой program_id, но он вам не понадобится - у вас будет имя исполняемого файла в столбце "программа" в диалоге statement_tracker. Если бы обновление выполнялось из анонимного блока PL/SQL, я не знаю, как его отследить - вам придется поэкспериментировать дальше.

Однако, может оказаться, что информации о osuser/machine/program/module достаточно, чтобы направить вас в нужное русло.

7
ответ дан 9 December 2019 в 22:35
поделиться
[

] Если это задание для базы данных по расписанию, то вы можете узнать, какие задания для базы данных по расписанию существуют, и посмотреть, что они делают. Другие вещи, которые вы можете сделать: [

]. [
    ] [
  • ] посмотрите на представления зависимостей, например, ALL_DEPENDENCIES, чтобы увидеть, какие пакеты/триггеры и т.д. используют эту таблицу. В зависимости от размера вашей системы, которая может возвращать много объектов для просмотра.[
  • ]. [
  • ][

    ] Ищите во всех исходных кодах БД ссылки на таблицу следующим образом:[

    ]. [

    ] выберите тип, имя. из all_source где lower(text) like lower('%mytable%');[

    ][
  • ] [
] [

] Опять же, это может вернуть много объектов, и, конечно, будут некоторые "ложные срабатывания", где строка поиска появляется, но на самом деле не является ссылкой на эту таблицу. Можно даже попробовать что-то более конкретное вроде:[

]. [
select distinct type, name
from   all_source
where lower(text) like lower('%insert into mytable%');
] [

], но, конечно, это пропустит случаи, когда команда была отформатирована по-другому. [

]. [

] Дополнительно, могут ли SQL-скрипты выполняться через задания "cron" на сервере? [

].
3
ответ дан 9 December 2019 в 22:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: