全库导入操作一直是我比较头疼的东西,一般情况下,我会尽量避免这种操作。但是对于有些情况,全库导入又几乎是唯一的选择,比如跨平台的数据库迁移、大版本升级等操作。
其实全库导入操作说起来很简单,令人比较头疼的是,导入过程中几乎不可避免的会出现大量的错误信息,这些错误有的可以忽略,有的可能造成系统的异常,本文试图通过各种方法尽量减少全库导入时错误的数量。
如果某些表空间不存在的话,全库导入操作会首先尝试创建表空间。所以在全库导入的时候,要么提前建立好所有必须的表空间,要么确保建立表空间的路径是存在的,且oracle用户拥有读写权限。
如果导入数据库采用默认安装的话,那么直接导入会产生什么问题呢:
$ imp "sys as sysdba" file=testmv_full.dmp full=y buffer=20480000 ignore=y log=testmv_full.log
用于大量重复用户存在,会报很多的唯一约束冲突的错误,不但会严重影响导入效率,而且产生包含大量错误信息的日志也会增加排错的难度和工作量。
更严重的是,在低于9205的一些版本中,导入操作会中途失败。具体情况可以参考:http://yangtingkun.itpub.net/post/468/214725
因此,为了避免上面提到的那些错误,尝试将那些会造成冲突的用户清除掉。删除用户列表为:
DROP USER ANONYMOUS CASCADE;
DROP USER OUTLN CASCADE;
DROP USER WMSYS CASCADE;
DROP USER ORDSYS CASCADE;
DROP USER ORDPLUGINS CASCADE;
DROP USER MDSYS CASCADE;
DROP USER CTXSYS CASCADE;
DROP USER XDB CASCADE;
DROP USER WKSYS CASCADE;
DROP USER WKPROXY CASCADE;
DROP USER ODM CASCADE;
DROP USER ODM_MTR CASCADE;
DROP USER OLAPSYS CASCADE;
DROP USER HR CASCADE;
DROP USER OE CASCADE;
DROP USER PM CASCADE;
DROP USER SH CASCADE;
DROP USER QS_ADM CASCADE;
DROP USER QS CASCADE;
DROP USER QS_WS CASCADE;
DROP USER QS_ES CASCADE;
DROP USER QS_OS CASCADE;
DROP USER QS_CBADM CASCADE;
DROP USER QS_CB CASCADE;
DROP USER QS_CS CASCADE;
删除用户后,使用同样的导入命令,错误大大减少。
检查日志文件,其中以IMP-开头的错误有2319个。而以ORA-开头的错误有1113个。其中发现大部分错误为ORA-00001,错误数为972个。都是SYSTEM用户下的表造成的。
于是,尝试在上面的基础上,删除SYSTEM用户下包含数据的表中的数据,重新执行导入操作,删除SYSTEM用户数据脚本如下:
SQL> SET SERVEROUT ON
SQL> DECLARE
2 V_CNT NUMBER := 0;
3 V_DEL NUMBER := 0;
4 V_LOOP NUMBER := 0;
5 V_RESULT NUMBER := 0;
6 BEGIN
7 <<LABLE_FOR_LOOP>>
8 FOR I IN (SELECT TABLE_NAME FROM USER_TABLES) LOOP
9 EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || I.TABLE_NAME INTO V_RESULT;
10 IF V_RESULT != 0 THEN
11 BEGIN
12 V_CNT := V_CNT + 1;
13 EXECUTE IMMEDIATE 'DELETE ' || I.TABLE_NAME;
14 V_DEL := V_DEL + 1;
15 EXCEPTION
16 WHEN OTHERS THEN
17 NULL;
18 END;
19 END IF;
20 END LOOP;
21 V_LOOP := V_LOOP + 1;
22 DBMS_OUTPUT.PUT_LINE(V_LOOP || ':' || ' COUNT ' || V_CNT || ', DEL ' || V_DEL);
23 IF V_CNT != V_DEL THEN
24 V_CNT := 0;
25 V_DEL := 0;
26 GOTO LABLE_FOR_LOOP;
27 END IF;
28 END;
29 /
1: COUNT 10, DEL 10
PL/SQL 过程已成功完成。
SQL> COMMIT;
提交完成。
下面重新执行导入工作。
这次错误信息进一步减少,其中IMP-错误还有375个,ORA-错误还有135个。检查错误信息中发现开始的时候遇到了很多用户不存在的问题。于是尝试删除用户后对象后,重新建立用户。
SQL> DECLARE
2 TYPE T_VARCHAR_TAB IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
3 V_DROP_STR T_VARCHAR_TAB;
4 V_CREATE_STR T_VARCHAR_TAB;
5 BEGIN
6 SELECT DBMS_METADATA.GET_DDL('USER', USERNAME) BULK COLLECT INTO V_CREATE_STR
7 FROM DBA_USERS
8 WHERE USERNAME NOT IN ('SYS', 'SYSTEM', 'DBSNMP');
9 SELECT 'DROP USER ' || USERNAME || ' CASCADE' BULK COLLECT INTO V_DROP_STR
10 FROM DBA_USERS
11 WHERE USERNAME NOT IN ('SYS', 'SYSTEM', 'DBSNMP');
12 FOR I IN 1..V_DROP_STR.COUNT LOOP
13 EXECUTE IMMEDIATE V_DROP_STR(I);
14 END LOOP;
15 FOR I IN 1..V_CREATE_STR.COUNT LOOP
16 EXECUTE IMMEDIATE V_CREATE_STR(I);
17 END LOOP;
18 END;
19 /
PL/SQL 过程已成功完成。
SQL> SET SERVEROUT ON
SQL> DECLARE
2 V_CNT NUMBER := 0;
3 V_DEL NUMBER := 0;
4 V_LOOP NUMBER := 0;
5 V_RESULT NUMBER := 0;
6 BEGIN
7 <<LABLE_FOR_LOOP>>
8 FOR I IN (SELECT TABLE_NAME FROM USER_TABLES) LOOP
9 EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || I.TABLE_NAME INTO V_RESULT;
10 IF V_RESULT != 0 THEN
11 BEGIN
12 V_CNT := V_CNT + 1;
13 EXECUTE IMMEDIATE 'DELETE ' || I.TABLE_NAME;
14 V_DEL := V_DEL + 1;
15 EXCEPTION
16 WHEN OTHERS THEN
17 NULL;
18 END;
19 END IF;
20 END LOOP;
21 V_LOOP := V_LOOP + 1;
22 DBMS_OUTPUT.PUT_LINE(V_LOOP || ':' || ' COUNT ' || V_CNT || ', DEL ' || V_DEL);
23 IF V_CNT != V_DEL THEN
24 V_CNT := 0;
25 V_DEL := 0;
26 GOTO LABLE_FOR_LOOP;
27 END IF;
28 END;
29 /
1: COUNT 10, DEL 10
PL/SQL 过程已成功完成。
SQL> COMMIT;
提交完成。
下面再次进行导入工作。错误进一步减少。这时IMP-错误还剩351个,ORA-错误还剩85个。
转载于:https://blog.51cto.com/dugu61888/1162139