oracle技术之系统触发器的应用顺序(四)
2013-05-16 09:16
465 查看
在写一个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状态的操作。
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html
通过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状态的操作。
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html
相关文章推荐
- oracle技术之系统触发器的应用顺序(三)
- Oracle VPD技术在中联his系统中的应用
- mysql和oracle的各种触发器应用
- 卡技术在应用系统开发中的运用
- 区块链技术不等于比特币等数字资产,溯源系统应用实例
- H.264的技术优势及其在H.323系统中的应用
- 《Oracle 高级复制技术介绍及应用》-HA技术-应用场景-实战演练
- oracle form 触发器执行顺序及键定义
- 利用 Oracle 系统触发器防止误删除操作
- TCL嵌入式测试技术在Comware V7系统中的应用
- JAVA-系统-【3】-java应用连接oracle正常,但是网页却报错java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
- 软件系统开发中的组件框架技术研究、设计和应用
- 系统架构、技术构架、应用构架 区别 .
- 【Oracle】触发器最系统入门学习指导
- Oracle技术之实例恢复的顺序
- oracle 一个表上的多个触发器的执行顺序
- CIO应用商业智能技术系统的重构思考
- 企业商业智能技术系统应用的重构思考
- [转]Oracle Form 触发器执行顺序