升级数据库时,比如从9i或者10g升级到11.2,官方文档强调需要禁用DDL trigger。
这里尤其要说的是OGG的DDL TRIGGER,如果升级前不禁用,很坑爹,具体参见《OGG DDL trigger造成升级数据库后大量SYS对象失效和数据库DDL失效》
那么什么是DDL trigger呢?
我们来做个测试:
21:07:17 @LUNAR>CREATE OR REPLACE TRIGGER Lunar_ddl_test BEFORE DROP ON DATABASE 21:08:54 2 21:08:54 3 BEGIN IF LOWER (ora_dict_obj_name ()) = 'test' 21:08:54 4 21:08:54 5 THEN 21:08:54 6 raise_application_error (num => -20000, 21:08:54 7 msg => 'Lunar test ' 21:08:54 8 || ora_dict_obj_name () 21:08:54 9 || ' ?!!!!!' 21:08:54 10 || 'Lunar test.....' 21:08:54 11 ); 21:08:54 12 END IF; 21:08:54 13 END; 21:08:54 14 / Trigger created. Elapsed: 00:00:00.01 21:09:26 @LUNAR>select OWNER,TRIGGER_NAME,TRIGGER_TYPE from dba_triggers where TRIGGER_NAME='LUNAR_DDL_TEST'; OWNER TRIGGER_NAME TRIGGER_TYPE ------------------------------ ------------------------------ ---------------- SYS LUNAR_DDL_TEST BEFORE EVENT Elapsed: 00:00:00.05 21:09:35 @LUNAR>
这里我们看到了,TRIGGER_TYPE为BEFORE EVENT,这个显然是DDL trigger。
那么还有哪些类似的呢,我们来查看一下:
20:59:14 @LUNAR>select distinct TRIGGER_TYPE from dba_triggers; TRIGGER_TYPE ---------------- BEFORE STATEMENT BEFORE EACH ROW AFTER EACH ROW BEFORE EVENT AFTER STATEMENT AFTER EVENT INSTEAD OF 7 rows selected. Elapsed: 00:00:00.00 20:59:19 @LUNAR>
上面trigger type,从名字也很容易看出,至少两种: BEFORE EVENT和AFTER EVENT。
如果查询trigger event,你会看到有明显的DDL字样的类型的trigger:
21:10:08 @LUNAR>select distinct TRIGGERING_EVENT from dba_triggers; TRIGGERING_EVENT ---------------------------------------- UPDATE OR DELETE DROP ALTER OR RENAME INSERT OR UPDATE OR DELETE INSERT OR UPDATE DELETE UPDATE DDL TRUNCATE RENAME CREATE OR ALTER OR DROP OR RENAME ALTER CREATE CREATE OR ALTER INSERT DROP OR TRUNCATE STARTUP 17 rows selected. Elapsed: 00:00:00.08 21:10:35 @LUNAR>
上述具体含义可以查询Oracle官方文档,大概解释如下:
事件 允许的时机 说明 STARTUP AFTER 启动数据库实例之后触发 SHUTDOWN BEFORE 关闭数据库实例之前触发(非正常关闭不触发) SERVERERROR AFTER 数据库服务器发生错误之后触发 LOGON AFTER 成功登录连接到数据库后触发 LOGOFF BEFORE 开始断开数据库连接之前触发 CREATE BEFORE,AFTER 在执行CREATE语句创建数据库对象之前、之后触发 DROP BEFORE,AFTER 在执行DROP语句删除数据库对象之前、之后触发 ALTER BEFORE,AFTER 在执行ALTER语句更新数据库对象之前、之后触发 DDL BEFORE,AFTER 在执行大多数DDL语句之前、之后触发 GRANT BEFORE,AFTER 执行GRANT语句授予权限之前、之后触发 REVOKE BEFORE,AFTER 执行REVOKE语句收权限之前、之后触犯发 RENAME BEFORE,AFTER 执行RENAME语句更改数据库对象名称之前、之后触犯发 AUDIT / NOAUDIT BEFORE,AFTER 执行AUDIT或NOAUDIT进行审计或停止审计之前、之后触发
那么文档中所说的禁用DDL trigger到底是哪一种呢?下面我们测试一下,如果不禁用DDL trigger会是什么情况。
首先我们查询当前数据库中的trigger_type in (‘BEFORE EVENT’,'AFTER EVENT’)的DDL:
21:10:35 @LUNAR>drop TRIGGER Lunar_ddl_test; Trigger dropped. Elapsed: 00:00:00.00 21:11:06 @LUNAR> 21:17:50 @LUNAR>select OWNER,TRIGGER_NAME,TRIGGER_TYPE from dba_triggers where trigger_type in ('BEFORE EVENT','AFTER EVENT'); OWNER TRIGGER_NAME TRIGGER_TYPE ------------------------------ ------------------------------ ---------------- SYS LOGMNRGGC_TRIGGER BEFORE EVENT SYS AW_TRUNC_TRG AFTER EVENT SYS AW_REN_TRG AFTER EVENT SYS AW_DROP_TRG AFTER EVENT WMSYS NO_VM_DDL BEFORE EVENT WMSYS NO_VM_DROP_A AFTER EVENT SYS CDC_ALTER_CTABLE_BEFORE BEFORE EVENT SYS CDC_CREATE_CTABLE_AFTER AFTER EVENT SYS CDC_CREATE_CTABLE_BEFORE BEFORE EVENT SYS CDC_DROP_CTABLE_BEFORE BEFORE EVENT EXFSYS EXPFIL_RESTRICT_TYPEEVOLVE BEFORE EVENT EXFSYS EXPFIL_ALTEREXPTAB_MAINT AFTER EVENT SYS XDB_PI_TRIG BEFORE EVENT EXFSYS EXPFIL_DROPOBJ_MAINT BEFORE EVENT EXFSYS EXPFIL_DROPUSR_MAINT AFTER EVENT EXFSYS RLMGR_TRUNCATE_MAINT BEFORE EVENT MDSYS SDO_DROP_USER AFTER EVENT MDSYS SDO_ST_SYN_CREATE BEFORE EVENT MDSYS SDO_TOPO_DROP_FTBL BEFORE EVENT MDSYS SDO_GEOR_BDDL_TRIGGER BEFORE EVENT MDSYS SDO_GEOR_ADDL_TRIGGER AFTER EVENT MDSYS SDO_NETWORK_DROP_USER AFTER EVENT SYSMAN MGMT_STARTUP AFTER EVENT 23 rows selected. Elapsed: 00:00:00.04
下面我们只把TRIGGERING_EVENT为DDL的trigger进行disable,然后执行数据库升级操作,之后来看看效果:
21:19:03 @LUNAR>select OWNER,TRIGGER_NAME,TRIGGER_TYPE,TRIGGERING_EVENT,status from dba_triggers where TRIGGERING_EVENT like 'DDL%'; OWNER TRIGGER_NAME TRIGGER_TYPE TRIGGERING_EVENT STATUS ------------------------------ ------------------------------ ---------------- ----------------------------------- -------- SYS GGS_DDL_TRIGGER_BEFORE BEFORE EVENT DDL DISABLED MDSYS SDO_GEOR_BDDL_TRIGGER BEFORE EVENT DDL DISABLED MDSYS SDO_GEOR_ADDL_TRIGGER AFTER EVENT DDL DISABLED SYS LOGMNRGGC_TRIGGER BEFORE EVENT DDL DISABLED Elapsed: 00:00:00.04 21:19:07 @LUNAR>
升级过程后续会单独写一个BLOG,这里不赘述。
升级过程没有任何报错,完美升级结束后,我们来检查一下数据库无效对象,发现确实有4个无效对象。
不过,数据库所有组件正如我们看到的升级过程一样,都是有效的,且已经升级成功:
19:04:56 sys@LUNAR>select owner,object_name,object_type,status from dba_objects where status != 'VALID' and owner in ('SYS','SYSTEM'); OWNER OBJECT_NAME OBJECT_TYPE STATUS ------------------------------ -------------------------------------------------- ------------------- ------- SYS DDLCTXINFO PACKAGE BODY INVALID Elapsed: 00:00:00.03 19:04:56 sys@LUNAR> 19:05:07 sys@LUNAR>SELECT SUBSTR(comp_id,1,15) comp_id, status, SUBSTR(version,1,10) version, SUBSTR(comp_name,1,35) comp_name FROM dba_registry; COMP_ID STATUS VERSION COMP_NAME ------------------------------ ---------------------- -------------------- ----------------------------------- OWB VALID 11.2.0.3.0 OWB APEX VALID 3.2.1.00.1 Oracle Application Express EM VALID 11.2.0.4.0 Oracle Enterprise Manager AMD VALID 11.2.0.4.0 OLAP Catalog SDO VALID 11.2.0.4.0 Spatial ORDIM VALID 11.2.0.4.0 Oracle Multimedia XDB VALID 11.2.0.4.0 Oracle XML Database CONTEXT VALID 11.2.0.4.0 Oracle Text EXF VALID 11.2.0.4.0 Oracle Expression Filter RUL VALID 11.2.0.4.0 Oracle Rules Manager OWM VALID 11.2.0.4.0 Oracle Workspace Manager CATALOG VALID 11.2.0.4.0 Oracle Database Catalog Views CATPROC VALID 11.2.0.4.0 Oracle Database Packages and Types JAVAVM VALID 11.2.0.4.0 JServer JAVA Virtual Machine XML VALID 11.2.0.4.0 Oracle XDK CATJAVA VALID 11.2.0.4.0 Oracle Database Java Packages APS VALID 11.2.0.4.0 OLAP Analytic Workspace XOQ VALID 11.2.0.4.0 Oracle OLAP API 18 rows selected. Elapsed: 00:00:00.01 19:05:07 sys@LUNAR> 19:05:07 sys@LUNAR>select count(*) from dba_objects where status='INVALID'; COUNT(*) ---------------- 4 Elapsed: 00:00:00.04 19:05:24 sys@LUNAR>select owner,object_type,count(*) from dba_objects where status='INVALID' group by owner,object_type; OWNER OBJECT_TYPE COUNT(*) ------------------------------ ------------------- ---------------- SYS PACKAGE BODY 1 OGG PACKAGE BODY 1 OGG FUNCTION 1 OGG PROCEDURE 1 Elapsed: 00:00:00.03 19:05:28 sys@LUNAR>select owner, object_name,object_type from dba_objects where status ='INVALID'; OWNER OBJECT_NAME OBJECT_TYPE ------------------------------ -------------------------------------------------- ------------------- SYS DDLCTXINFO PACKAGE BODY OGG DDLORA_GETLOBS PROCEDURE OGG FILTERDDL FUNCTION OGG DDLAUX PACKAGE BODY Elapsed: 00:00:00.02 19:05:33 sys@LUNAR>
上面看到有3个是OGG的,不用想,这个坑爹的OGG DDL功能造成的,另外一个SYS的DDLCTXINFO,这个比较眼生,检查它是什么来路:
20:02:47 sys@LUNAR>20:02:47 sys@LUNAR>select dbms_metadata.get_ddl('PACKAGE','DDLCTXINFO','SYS') from dual; CREATE OR REPLACE PACKAGE "SYS"."DDLCTXINFO" AS PROCEDURE setCtxInfo(objNum IN NUMBER, baseObjNum IN NUMBER, objUserId IN NUMBER, baseObjUserId IN NUMBER, baseObjProperty IN NUMBER) ; END DDLCtxInfo ; CREATE OR REPLACE PACKAGE BODY "SYS"."DDLCTXINFO" AS PROCEDURE setCtxInfo(objNum IN NUMBER, baseObjNum IN NUMBER, objUserId IN NUMBER, baseObjUserId IN NUMBER, baseObjProperty IN NUMBER) IS BEGIN "OGG".DDLReplication.setCtxInfo(objNum , baseObjNum , objUserId , baseObjUserId , baseObjProperty ) ; END; END DDLCtxInfo; Elapsed: 00:00:00.41 20:02:47 sys@LUNAR>
可见,还是OGG DDL的东西,于是清理上述4个无效对象:
20:02:51 sys@LUNAR>drop PACKAGE BODY SYS.DDLCTXINFO; Package body dropped. Elapsed: 00:00:00.03 20:02:52 sys@LUNAR>drop PROCEDURE OGG.DDLORA_GETLOBS; Procedure dropped. Elapsed: 00:00:00.00 20:02:57 sys@LUNAR>drop FUNCTION OGG.FILTERDDL; Function dropped. Elapsed: 00:00:00.01 20:02:58 sys@LUNAR>drop PACKAGE BODY OGG.DDLAUX; Package body dropped. Elapsed: 00:00:00.02 20:02:58 sys@LUNAR>
再次检查,已经没有无效对象,且数据库组件全部有效:
20:02:59 sys@LUNAR>select owner,object_name,object_type,status from dba_objects where status != 'VALID' and owner in ('SYS','SYSTEM'); no rows selected Elapsed: 00:00:00.02 20:06:00 sys@LUNAR>select owner, object_name,object_type from dba_objects where status ='INVALID'; no rows selected Elapsed: 00:00:00.01 20:06:01 sys@LUNAR> [oracle@dm01db01 ~]$ ss SQL*Plus: Release 11.2.0.4.0 Production on Sun May 3 20:07:10 2015 Copyright (c) 1982, 2013, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP, Data Mining and Real Application Testing options 20:07:10 sys@LUNAR>col COMP_NAME for a35 20:07:18 sys@LUNAR>SELECT SUBSTR(comp_id,1,15) comp_id, status, SUBSTR(version,1,10) version, SUBSTR(comp_name,1,35) comp_name FROM dba_registry; COMP_ID STATUS VERSION COMP_NAME ------------------------------ ---------------------- -------------------- ----------------------------------- OWB VALID 11.2.0.3.0 OWB APEX VALID 3.2.1.00.1 Oracle Application Express EM VALID 11.2.0.4.0 Oracle Enterprise Manager AMD VALID 11.2.0.4.0 OLAP Catalog SDO VALID 11.2.0.4.0 Spatial ORDIM VALID 11.2.0.4.0 Oracle Multimedia XDB VALID 11.2.0.4.0 Oracle XML Database CONTEXT VALID 11.2.0.4.0 Oracle Text EXF VALID 11.2.0.4.0 Oracle Expression Filter RUL VALID 11.2.0.4.0 Oracle Rules Manager OWM VALID 11.2.0.4.0 Oracle Workspace Manager CATALOG VALID 11.2.0.4.0 Oracle Database Catalog Views CATPROC VALID 11.2.0.4.0 Oracle Database Packages and Types JAVAVM VALID 11.2.0.4.0 JServer JAVA Virtual Machine XML VALID 11.2.0.4.0 Oracle XDK CATJAVA VALID 11.2.0.4.0 Oracle Database Java Packages APS VALID 11.2.0.4.0 OLAP Analytic Workspace XOQ VALID 11.2.0.4.0 Oracle OLAP API 18 rows selected. Elapsed: 00:00:00.00 20:07:25 sys@LUNAR>
总结:
1,数据库升级前,一定要检查OGG用户的DDL功能是否已经被禁用,如果没有,麻利儿禁用它
2,其他系统自带的DDL trigger一般来说,如果是11.2小版本之间的升级,个人感觉不禁用也问题不大
3,官方建议升级前禁用DDL trigger,因此,推荐升级前还是禁用吧。尤其是从9i或者10g升级到11.2.