2010-01-05 39 views
5

我想知道是否有可能找出包中的哪個包或過程正在更新表?如何找出哪個程序包/程序正在更新表格?

由於某個項目正在交付(交出項目的人已經離開),沒有適當的文檔,我們知道我們已更新的數據總是會回到一些奇怪的來源點。

我們猜測這可能是數據庫作業或調度程序在我們不知情的情況下運行update命令。我希望有一種方法可以找出源代碼調用的來源,即更新表並將源作爲觸發器插入到我們正在監控的表上。

任何想法?

謝謝。

回答

3

如果它是一個計劃的數據庫作業,那麼您可以找出計劃的數據庫作業存在和看看他們做什麼。其他事情你可以做的是:

  • 看看依賴性視圖例如, ALL_DEPENDENCIES查看哪些軟件包/觸發器等使用該表。取決於你的系統的大小,可能會返回很多對象來拖網。
  • 搜索所有的數據庫來源這樣表中引用的代碼:

    從ALL_SOURCE 選擇不同的類型,名稱 其中較低(文本)等低級(「%MYTABLE%」);

同樣可能返回大量的對象,當然也會有一些「假陽性」,其中搜索字符串出現,但實際上不是該表的參考。你甚至可以嘗試更具體的東西,如:

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

但當然,這將錯過命令格式不同的情況。

此外,是否可以通過服務器上的「cron」作業運行SQL腳本?

+0

嗨託尼, 感謝您的更新。我已經檢查了所有在cron的用戶,並懷疑一個調度程序是否導致更新.. 我會嘗試運行提示的sql語句...再次感謝.. – N2EE 2010-01-08 06:29:42

7

更新:我戳了一圈,發現了 如何跟蹤聲明回其擁有 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>; 

你可能想保護的INSERT語句在一定條件下,只有使改變你intere當登錄觸發器正在發生 - 在我的測試服務器上,這個語句的運行速度很慢(1秒),所以我不想記錄所有這些更新。當然,在這種情況下,您需要將觸發器更改爲行級別,以便檢查:新值或舊值。如果您真的擔心select的開銷,可以將其更改爲不針對v $ sql進行連接,而只保存SQL_ADDRESS列,然後使用DBMS_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信息可能足以讓您指出正確的方向。

1

只需編寫一個「更新後」觸發器,並在此觸發器中將「DBMS_UTILITY.FORMAT_CALL_STACK」的結果記錄在專用表中。

這個函數的目的正是爲了給你完整的存儲過程和觸發器的調用堆棧,以觸發你的代碼。 我是從移動應用程序寫的,所以我不能給你更詳細的例子,但如果你谷歌它,你會發現很多。

0

如果你在本地工作,並且只對改變數據的第一件事感興趣,那麼一個快速和髒的選項就是在觸發器中拋出一個錯誤而不是記錄。這樣一來,你平時的堆棧跟蹤,它是少了很多打字,你並不需要創建一個新表:

AFTER UPDATE ON table_of_interest 
BEGIN 
    RAISE_APPLICATION_ERROR(-20001, 'something changed it'); 
END; 
/
相關問題