网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 数据库 > SQL技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
数据库:数据库教程,数据库技巧,Oracle教程,MySQL教程,Sybase教程,Access教程,DB2教程,数据库安全,数据库文摘
本月文章推荐
.配置SQL Server文件组对应不同的.
.教你轻松掌握SQL Server错误信息.
.用共享游标提升 SQL 性能.
.SQL Server 2000启动1069错误(由.
.SQL Server数据库内存会不断增加.
.Sql server优化50法.
.简化SQL语句一例.
.sa登陆失败 SQL Server错误18456.
.拷贝的SQL Server 7数据库的恢复.
.SQL Server2000 索引结构及其使用.
.建索引(尤其是主键)时请注意索.
.SELECT语句中“加锁选项”功能说.
.依赖于其他表格的标准轻松在表格.
.滥用触发器会造成数据库及应用程.
.高级复制中mlog$表的HWM过高导致.
.探讨大型项目中的主要问题─数据.
.一次特殊的SQL Server安装奇遇.
.SQL技巧:创建用来按小时报告的查.
.利用sql2005的新特性实现根据子表.
.where子句在编写过程中需要注意的.

DBA:在生产环境中创建监控表DML的触发器

发表日期:2008-7-11


在生产环境中,总是可能出现这样的情况:某张或者某些表的数据被莫名其妙的修改了,但是很难定位出是哪个用户、哪个过程修改的。这是一个很让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了。


当一条INSERT或者UPDATE语句执行以后才会触发触发器,所以这时候的游标状态是CURFETCH,我们这就通过状态为CURFETCH来定位。

上一篇:PowerDesigner实现导出的SQL语句附带主键 人气:1033
下一篇:通过作业调度建立SQL Server的自动备份 人气:800
浏览全部DBA的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐