【賽迪網-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標記就可以在唯讀模式下執行它。這可以防止任何程序寫入檔案系統。任...