oracle触发器 乱序,oracle技术之系统触发器的应用顺序(四)

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

通过TRACE检查问题的原因。

根据前面文章的测试,可以发现,是由于用户引发的SUSPEND事件导致一个存在编译错误的触发器执行,从这个触发器执行以后,当前会话不在尝试调用触发器。

下面通过TRACE来比较三种不同的情况:

SQL> DROP TABLE T_TRIGGER;

表已删除。

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  BEGIN

6   INSERT INTO YANGTK.T_TRIGGER VALUES ('SYS TRIGGER');

7   COMMIT;

8  END;

9  /

触发器已创建

SQL> CONN YANGTK/YANGTK

已连接。

SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

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> ALTER SESSION ENABLE RESUMABLE TIMEOUT 300;

会话已更改。

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';

会话已更改。

SQL> CREATE TABLE T_BIG (ID NUMBER)

2  TABLESPACE YANGTK

3  STORAGE (INITIAL250M);

CREATE TABLE T_BIG (ID NUMBER)

*

第1行出现错误:

ORA-30032:挂起的(可恢复)语句已超时

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

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';

会话已更改。

首先记录正常情况下的TRACE信息,随后是出错时的TRACE信息,为了方便对比结果,这里重新连接,好得到新的TRACE文件:

SQL> CONN YANGTK/YANGTK

已连接。

SQL> TRUNCATE TABLE T_TRIGGER;

表被截断。

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 T_TRIGGER VALUES ('YANGTK TRIGGER');

21   COMMIT;

22  END;

23  /

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

SQL> ALTER SESSION ENABLE RESUMABLE TIMEOUT 300;

会话已更改。

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';

会话已更改。

SQL> CREATE TABLE T_BIG (ID NUMBER)

2  TABLESPACE YANGTK

3  STORAGE (INITIAL250M);

CREATE TABLE T_BIG (ID NUMBER)

*

第1行出现错误:

ORA-04098:触发器'YANGTK.TRI_SUSPEND'无效且未通过重新验证

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

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';

会话已更改。

下面删掉错误的TRIGGER,然后再次生成TRACE,记录发生错误后,Oracle在后台做了哪些操作:

SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';

会话已更改。

SQL> CREATE TABLE T_BIG (ID NUMBER)

2  TABLESPACE YANGTK

3  STORAGE (INITIAL250M);

CREATE TABLE T_BIG (ID NUMBER)

*

第1行出现错误:

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

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';

会话已更改。

对比三次操作生成的TRACE信息,发现对于最后一次的调用,Oracle根本没有去尝试读取任何触发器相关的信息。其实,不只是Oracle没有读取触发器的信息,Oracle实现上根本就没有进入SUSPEND的状态,换句话说,如果SUSPEND触发器失效的时候被调用,不是简单的阻止SUSPEND触发器再次被调用,而是使得当前会话无法在进入SUSPEND状态。

当前会话采用何种方式都无法在进入SUSPEND状态,即使关闭RESUMABLE,再重新打开:

SQL> ALTER SESSION DISABLE RESUMABLE;

会话已更改。

SQL> ALTER SESSION ENABLE RESUMABLE TIMEOUT 300;

会话已更改。

SQL> SELECT * FROM T_TRIGGER;

INFO

--------------------

SYS TRIGGER

SQL> CREATE TABLE T_BIG (ID NUMBER)

2  TABLESPACE YANGTK

3  STORAGE (INITIAL250M);

CREATE TABLE T_BIG (ID NUMBER)

*

第1行出现错误:

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

SQL> SELECT * FROM T_TRIGGER;

INFO

--------------------

SYS TRIGGER

由于TRACE文件太大,且绝大部分内容都与当前问题无关,这里就不贴出结果了。不过发现一个有趣的现象,第一次操作由于进入了SUSPEND状态,等待了5分钟的时间,导致TRACE文件最大,居然有70多万行。根据TRACE的内容可以看到,Oracle处于SUSPEND的状态下,并非只是简单的等待,而是会不断的重新检查当前系统十分有足够的空间来完全当前处于SUSPEND状态的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值