DBA 在生產環境中建立監控表DML的觸發器

2021-04-18 22:08:06 字數 3412 閱讀 4795

【賽迪網-it技術報道】在生產環境中,總是可能出現這樣的情況:某張或者某些表的資料被莫名其妙的修改了,但是很難定位出是哪個使用者、哪個過程修改的。這是乙個很讓dba頭痛的事情(往往dba對於整個**邏輯並不是非常了解)。要定位出「問題」語句,有幾種方法可以選擇:log miner;細節粒度審計;觸發器。log miner要求要有歸檔日誌(這個並非所有系統都可以做),而且需要有相當的磁碟空間,好處就是可以離線做;細節粒度公升級能夠根據條件記錄下表的dml操作(9i及之前只能記錄select語句),比較複雜的fga需要較高許可權的使用者來實現;觸發器比較靈活,能夠按照比較複雜的條件來記錄需要的資訊。下面介紹觸發器如何實現。

要建立這樣的觸發器,需要利用到幾張系統檢視:v$session, v$sql, v$cursor,(10g, 9.2.0.1中可以,9.2.0.5, 9.2.0.之前存在bug)

sql> connect "/ as sysdba"

grant select on sys.v_$sql to demo;

grant select on sys.v_$sql_bind_data to demo;

grant select on sys.v_$sql_cursor to demo;

grant select on sys.v_$session to demo;

grant create trigger to demo;

create table trig_sql(lt date, sid number, serial# number,

username varchar2(30), osuser varchar2(64),

machine varchar2(32), terminal varchar2(16),

program varchar2(64), sqltext varchar2(2000),

status varchar2(30));

方法1:

create or replace trigger ttt_trig

after insert or update on pga_ttt

declare

pragma autonomous_transaction;

begin

insert into trig_sql

select sysdate,s.sid, s.serial#, s.username, s.osuser,

s.machine, s.terminal, s.program, q.sql_text line,

'none'

from v$sql q, v$session s

where s.audsid=(select userenv('sessionid') from dual)

and s.prev_sql_addr=q.address

and s.prev_hash_value = q.hash_value;

commit;

end;

方法2:

create or replace trigger ttt_trig

after insert or update on pga_ttt

declare

pragma autonomous_transaction;

begin

for cr in (select s.sid, s.serial#, s.username, s.osuser,

s.machine, s.terminal, s.program,

q.sql_text line, c.status stat

from v$sql q, v$sql_cursor c, v$session s

where s.audsid=(select userenv('sessionid') from dual)

and s.prev_sql_addr=q.address

and c.status = 'curfetch')

loop

insert into trig_sql values(sysdate, cr.sid, cr.serial#,

cr.username, cr.osuser, cr.machine,

cr.terminal, cr.program, cr.line,

cr.stat);

end loop;

commit;

end;

第一種方法是通過前一sql的位址(pre_sql_addr)和hash(prev_hash_value)值來定位出發trigger的語句的,不能用sql_address和hash_value來定位,否則獲取到是觸發器裡面向日誌表插入記錄資料的語句本身了。

第二個方法是通過通過位址加游標的方法,按照檢視各個欄位的解釋,應該是可以通過v$sql_cursor.parent_handle來定位的。但是通過測試發現,只有當前一條語句和查詢前一條語句的語句在乙個plsql塊中的時候才有效,

sql> set serveroutput on

sql> declare

2 v_date date;

3 v_sql varchar2(2000);

4 begin

5 select sysdate into v_date from dual;

6 7 select q.sql_text into v_sql

8 from v$sql q, v$sql_cursor c, v$session s

9 where s.audsid=(select userenv('sessionid') from dual)

10 and s.prev_sql_addr=q.address and q.address=c.parent_handle;

11 12 dbms_output.put_line(v_sql);

13 end;

14 /

select sysdate from dual

pl/sql procedure successfully completed.

因為觸發器本身是乙個plsql塊,所以總是無法獲得正確語句,最後只有通過cursor的狀態來獲取。下面簡單了解一下cursor各個狀態的含義:

·curnull:游標已經存在,但沒有任何sql語句在使用它(即cache在每個session記憶體中的游標)

·cursyntax:解析sql語句過程的乙個游標狀態,說明呼叫游標的sql語句語法正確,但是沒有解析完成。

·curparse:呼叫游標的語句解析完畢

·curbound:游標使用了幫定變數,並定義好了幫定變數

·curfetch:游標執行完畢,並fetch了資料

·currow:游標正指向某一行

·error:游標錯誤,一般是有bug了。

在生產環境中修改MySQL庫表結構

如果我們需要在生產環境中修改mysql資料庫中某個庫表的結構。那麼,需要考慮哪些要點,才能確保不會出問題呢?這裡先描述一下我在生產環境mysql資料庫中修改庫表結構時遇到的問題。在開發過程中,我發現mysql中某個庫表需要新增乙個字段,比如庫表 需要給sname後面新增乙個字段 sheight。那麼...

在生產環境中安全地執行Docker容器

在生產環境中,強化docker容器的一種方法就是使它們不可變,也就是唯讀。安全地執行容器的其他方法還包括最小化受攻擊面和應用linux安全過程,標準linux安全過程和針對容器環境的特定過程都要應用。u0026 xd n u0026 xd n 在啟動容器時傳入 read only標記就可以在唯讀模式...

在生產環境中安全地執行Docker容器

在生產環境中,強化docker容器的一種方法就是使它們不可變,也就是唯讀。安全地執行容器的其他方法還包括最小化受攻擊面和應用linux安全過程,標準linux安全過程和針對容器環境的特定過程都要應用。在啟動容器時傳入 read only標記就可以在唯讀模式下執行它。這可以防止任何程序寫入檔案系統。任...