yangtingkun
===========================================================
系统触发器的应用顺序(三)
===========================================================

在写一个AFTER SUSPEND触发器的时候碰到了一个很有趣的现象。

寻找导致问题的原因。

系统触发器的应用顺序(一):http://yangtingkun.itpub.net/post/468/486884

系统触发器的应用顺序(二):http://yangtingkun.itpub.net/post/468/486915


上一篇文章介绍了,如果当前用户下的触发器出现了编译错误,则会导致其他触发器也无法触发,即使当前触发器被删除。

是什么原因导致了这种情况的产生,怀疑可能与触发器的运行顺序有关,由于触发器的运行是根据触发器的建立顺序,具体描述可以参考:http://yangtingkun.itpub.net/post/468/398314

下面将SYS用户下的触发器和当前用户下的触发器建立顺序倒置,看看是否出现同样的问题:

SQL> DROP TABLE T_TRIGGER PURGE;

表已删除。

SQL> CREATE TABLE T_TRIGGER (INFO VARCHAR2(20));

表已创建。

SQL> CONN / AS SYSDBA已连接。
SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

SQL> CREATE OR REPLACE TRIGGER TRI_SUSPEND
2 AFTER SUSPEND ON DATABASE
3 DECLARE
4 PRAGMA AUTONOMOUS_TRANSACTION;
5 V_RESULT BOOLEAN;
6 V_ERROR_TYPE VARCHAR2(32767);
7 V_OBJECT_TYPE VARCHAR2(32767);
8 V_OBJECT_OWNER VARCHAR2(30);
9 V_TABLESPACE_NAME VARCHAR2(30);
10 V_OBJECT_NAME VARCHAR2(128);
11 V_SUB_OBJECT_NAME VARCHAR2(128);
12 BEGIN
13 V_RESULT := DBMS_RESUMABLE.SPACE_ERROR_INFO(
14 V_ERROR_TYPE,
15 V_OBJECT_TYPE,
16 V_OBJECT_OWNER,
17 V_TABLESPACE_NAME,
18 V_OBJECT_NAME,
19 V_SUB_OBJECT_NAME);
20 INSERT INTO YANGTK.T_TRIGGER VALUES ('SYS TRIGGER');
21 COMMIT;
22 END;
23 /

触发器已创建

SQL> CONN YANGTK/YANGTK已连接。
SQL> DROP TRIGGER TRI_SUSPEND;
DROP TRIGGER TRI_SUSPEND
*
1 行出现错误:
ORA-04080:
触发器 'TRI_SUSPEND' 不存在


SQL> CREATE OR REPLACE TRIGGER TRI_SUSPEND
2 AFTER SUSPEND ON DATABASE
3 DECLARE
4 PRAGMA AUTONOMOUS_TRANSACTION;
5 V_RESULT BOOLEAN;
6 V_ERROR_TYPE VARCHAR2(32767);
7 V_OBJECT_TYPE VARCHAR2(32767);
8 V_OBJECT_OWNER VARCHAR2(30);
9 V_TABLESPACE_NAME VARCHAR2(30);
10 V_OBJECT_NAME VARCHAR2(128);
11 V_SUB_OBJECT_NAME VARCHAR2(128);
12 BEGIN
13 V_RESULT := DBMS_RESUMABLE.SPACE_ERROR_INFO(
14 V_ERROR_TYPE,
15 V_OBJECT_TYPE,
16 V_OBJECT_OWNER,
17 V_TABLESPACE_NAME,
18 V_OBJECT_NAME,
19 V_SUB_OBJECT_NAME);
20 INSERT INTO T_TRIGGER VALUES ('YANGTK TRIGGER');
21 COMMIT;
22 END;
23 /

警告: 创建的触发器带有编译错误。

SQL> ALTER SESSION ENABLE RESUMABLE TIMEOUT 300;

会话已更改。

SQL> CREATE TABLE T_BIG (ID NUMBER)
2 TABLESPACE YANGTK
3 STORAGE (INITIAL 250M);
CREATE TABLE T_BIG (ID NUMBER)
*
1 行出现错误:
ORA-04098:
触发器 'YANGTK.TRI_SUSPEND' 无效且未通过重新验证

ORA-01659:
无法分配超出 27 MINEXTENTS (在表空间 YANGTK )


SQL> SELECT * FROM T_TRIGGER;

INFO
--------------------
SYS TRIGGER

SQL> SELECT OBJECT_ID, OWNER
2 FROM DBA_OBJECTS
3 WHERE OBJECT_NAME = 'TRI_SUSPEND';

OBJECT_ID OWNER
---------- ------------------------------
92651 SYS
92652 YANGTK

虽然错误信息一样,但是可以看到,这次T_TRIGGER表中包含一条记录,说明SYS触发器已经执行成功了。是在尝试调用第二个触发器YANGTK用户下的触发器时出现的错误。

SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

SQL> CREATE TABLE T_BIG (ID NUMBER)
2 TABLESPACE YANGTK
3 STORAGE (INITIAL 250M);
CREATE TABLE T_BIG (ID NUMBER)
*
1 行出现错误:
ORA-01659:
无法分配超出 27 MINEXTENTS (在表空间 YANGTK )


SQL> SELECT * FROM T_TRIGGER;

INFO
--------------------
SYS TRIGGER

可以看到,就是由于触发器状态的不正确,导致当前会话调用触发器出现了问题。即使删除了问题触发器,发生了SUSPEND事件后,SYS用户下的AFTER SYSPEND也没有再次被触发。

尝试在当前会话再次添加一个正确的触发器:

SQL> CREATE OR REPLACE TRIGGER TRI_SUSPEND
2 AFTER SUSPEND ON DATABASE
3 DECLARE
4 PRAGMA AUTONOMOUS_TRANSACTION;
5 BEGIN
6 INSERT INTO T_TRIGGER VALUES ('YANGTK TRIGGER');
7 COMMIT;
8 END;
9 /

触发器已创建

SQL> CREATE TABLE T_BIG (ID NUMBER)
2 TABLESPACE YANGTK
3 STORAGE (INITIAL 250M);
CREATE TABLE T_BIG (ID NUMBER)
*
1 行出现错误:
ORA-01659:
无法分配超出 27 MINEXTENTS (在表空间 YANGTK )


SQL> SELECT * FROM T_TRIGGER;

INFO
--------------------
SYS TRIGGER

即使重建当前用户下的触发器,使其状态正确,在当前的会话中,Oracle也不会再次调用触发器了。

yangtingkun 发表于:2009.07.03 23:28 ::分类: ( ORACLE ) ::阅读:(713次) :: 评论 (0)

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


切换风格
新闻聚合
博客日历
文章归档...
最新发表...
最新评论...
最多阅读文章...
最多评论文章...
博客统计...
Blog信息
网站链接...