千家信息网

从SQLFile文件分析Oracle Data Pump数据导入行为

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,在之前的文章《三个使用数据泵(Data Pump)的小技巧》(http://space.itpub.net/17203031/viewspace-768245)里面,我们介绍了使用SQLFILE参数,
千家信息网最后更新 2025年02月02日从SQLFile文件分析Oracle Data Pump数据导入行为

在之前的文章《三个使用数据泵(Data Pump)的小技巧》(http://space.itpub.net/17203031/viewspace-768245)里面,我们介绍了使用SQLFILE参数,可以输出Data Pump数据泵生成的DDL语句和对应的系列SQL语句。本篇,我们针对之前的结果,分析一下SQLFILE生成文件,从而了解一下Oracle Data Pump是怎么导入数据的。

1、环境介绍和背景介绍

我们依然选择Oracle 11g进行试验。

SQL> select * from v$version;

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

PL/SQL Release 11.2.0.1.0 - Production

CORE 11.2.0.1.0 Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production

作为上篇的续文,依然使用上篇的directory对象和dmp文件。

SQL> select directory_name, directory_path from dba_directories where directory_name='DUMPTEST';

DIRECTORY_NAME DIRECTORY_PATH

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

DUMPTEST /dumptest

[oracle@bspdev dumptest]$ ls -l

-rw-r----- 1 oracle oinstall 109694976 Aug 12 03:34 scott.dmp

-rw-r----- 1 oracle oinstall 109690880 Aug 12 05:32 scott_par.dmp

调用impdp语句进行数据导入,生成SQLFile

[oracle@bspdev dumptest]$ impdp \"/ as sysdba\" directory=dumptest dumpfile=scott.dmp sqlfile=scott_all.sql

Import: Release 11.2.0.1.0 - Production on Thu Aug 15 05:02:47 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

Master table "SYS"."SYS_SQL_FILE_FULL_01" successfully loaded/unloaded

Starting "SYS"."SYS_SQL_FILE_FULL_01": "/******** AS SYSDBA" directory=dumptest dumpfile=scott.dmp sqlfile=scott_all.sql

Processing object type SCHEMA_EXPORT/USER

Processing object type SCHEMA_EXPORT/SYSTEM_GRANT

Processing object type SCHEMA_EXPORT/ROLE_GRANT

Processing object type SCHEMA_EXPORT/DEFAULT_ROLE

Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA

Processing object type SCHEMA_EXPORT/TABLE/TABLE

Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX

Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT

Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS

Processing object type SCHEMA_EXPORT/VIEW/VIEW

Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT

Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS

Job "SYS"."SYS_SQL_FILE_FULL_01" successfully completed at 05:02:59

[oracle@bspdev dumptest]$ ls -l | grep scott_all

-rw-r--r-- 1 oracle oinstall 71324 Aug 15 05:02 scott_all.sql

我们通过FTP获取到sql文件,进行分析。生成的文件体积较大,下面分为若干段结构进行分析。

2、会话修改和跟踪时间片段

trace文件中,我们首先看到的是一系列的alter session命令片段。

-- CONNECT SYS

ALTER SESSION SET EVENTS '10150 TRACE NAME CONTEXT FOREVER, LEVEL 1';

ALTER SESSION SET EVENTS '10904 TRACE NAME CONTEXT FOREVER, LEVEL 1';

ALTER SESSION SET EVENTS '25475 TRACE NAME CONTEXT FOREVER, LEVEL 1';

ALTER SESSION SET EVENTS '10407 TRACE NAME CONTEXT FOREVER, LEVEL 1';

ALTER SESSION SET EVENTS '10851 TRACE NAME CONTEXT FOREVER, LEVEL 1';

ALTER SESSION SET EVENTS '22830 TRACE NAME CONTEXT FOREVER, LEVEL 192 ';

能够使用Data Pump的用户,要求具有DATAPUMP_IMP_FULL_DATABASE角色权限。这些事件显然属于Oracle内部的环境准备。

我们通过一些方法,可以知道10000-10999时间编号的方法。

ORA-10150: import exceptions

ORA-10904: Allow locally managed tablespaces to have user allocation

ORA-10407: enable datetime TIME datatype creation

ORA-10851: Allow Drop command to drop queue tables

ORA-22830: 使 VARRAY 列能创建为 OCT 的事件

ORA-25475:与流Stream相关的事件

通过这些等待事件的设置,主要是处于将工作保证,对一些系统环境进行重置。防止潜在问题的出现和便于导入过程。

3、用户创建和权限设置

Data Pump是会自动的创建出用户信息,并且给用户赋予相应的权限。首先是用户创建。

-- new object type path: SCHEMA_EXPORT/USER

-- CONNECT SYSTEM

CREATE USER "SCOTT" IDENTIFIED BY VALUES 'S:CB685EC52372362B49B7EC43AB0B04BCAF2C71F283C5A558FF8E430F5365;F894844C34402B67'

DEFAULT TABLESPACE "USERS"

TEMPORARY TABLESPACE "TEMP";

注意,用户密码是以密文方式显示出来,保证了原有数据。同时Default TablespaceTempory Tablespace都是明确的指定出来。这也就是为什么我们在使用Data Pump导入数据的时候,用户可以不创建,但是表空间一定要规划好。如果表空间规划有问题,用户创建失败,后面所有的对象就是一连串的失败信息,导入也就没有意义了。

用户创建之后,就可以根据系统权限、角色权限和对象权限的类型进行权限赋予。

-- new object type path: SCHEMA_EXPORT/SYSTEM_GRANT

GRANT EXECUTE ANY PROCEDURE TO "SCOTT";

GRANT CREATE VIEW TO "SCOTT";

GRANT SELECT ANY TABLE TO "SCOTT";

GRANT UNLIMITED TABLESPACE TO "SCOTT";

-- new object type path: SCHEMA_EXPORT/ROLE_GRANT

GRANT "CONNECT" TO "SCOTT";

GRANT "RESOURCE" TO "SCOTT";

GRANT "SELECT_CATALOG_ROLE" TO "SCOTT";

-- new object type path: SCHEMA_EXPORT/DEFAULT_ROLE

ALTER USER "SCOTT" DEFAULT ROLE ALL;

注意:一个常见的问题是,Oracle Data Pump回去创建用户的赋予权限。但是对角色Role,如果事先没有,Oracle是会报错的。

4Schema处理

在下面,我们看到了调用pl/sql匿名块过程,调用oracle SYS用户下的存储过程。

-- new object type path: SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA

-- CONNECT SCOTT

BEGIN

sys.dbms_logrep_imp.instantiate_schema(schema_name=>SYS_CONTEXT('USERENV','CURRENT_SCHEMA'), export_db_name=>'WILSON', inst_scn=>'3501442');

COMMIT;

END;

/

这个方法是一个内部方法,代码是被wrap过的。笔者不知道这个方法的作用。只能猜测是和Data Pump工作过程中Schema初始化有关的操作。其中参数还包括SCN编号。

5、数据表DDL创建

下面就是数据表DDL语句,所有数据对象DDL,都是全文显示。其中包括了Segment信息和Table Annotation

-- new object type path: SCHEMA_EXPORT/TABLE/TABLE

-- CONNECT SYS

CREATE TABLE "SCOTT"."DEPT"

( "DEPTNO" NUMBER(2,0),

"DNAME" VARCHAR2(14 BYTE),

"LOC" VARCHAR2(13 BYTE)

) SEGMENT CREATION IMMEDIATE

PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "USERS" ;

CREATE TABLE "SCOTT"."EMP"

( "EMPNO" NUMBER(4,0),

"ENAME" VARCHAR2(10 BYTE),

"JOB" VARCHAR2(9 BYTE),

"MGR" NUMBER(4,0),

"HIREDATE" DATE,

"SAL" NUMBER(7,2),

"COMM" NUMBER(7,2),

"DEPTNO" NUMBER(2,0)

) SEGMENT CREATION IMMEDIATE

PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "USERS" ;

这里面注意几个问题:

ü 数据表创建过程中,使用的DDL语句是"全文"的。也就是包括了定义一个数据表的全部参数,其中有一些我们平时很少接触,或者其他版本不能支持的特性。如果遇到了兼容性问题,可以在SQLFile中直接修改;

ü 表空间,我们说的是数据表段的表空间是再此指定的。如果表空间不存在,Data Pump是不会创建数据表,并且报错。进而后面的数据Import失败。所以,保证表空间存在也是一个必要条件;

ü 这里面只包括了数据定义,不包括索引、参照约束;

6Index创建

之后就是创建索引对象。针对不同的索引类型,集中对所有索引进行创建。严格的说,索引Index也是一种段结构,段结构参数,如初始extent大小,都是需要定义出来的。

-- new object type path: SCHEMA_EXPORT/TABLE/INDEX/INDEX

-- CONNECT SCOTT

CREATE UNIQUE INDEX "SCOTT"."PK_DEPT" ON "SCOTT"."DEPT" ("DEPTNO")

PCTFREE 10 INITRANS 2 MAXTRANS 255

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "USERS" PARALLEL 1 ;

ALTER INDEX "SCOTT"."PK_DEPT" NOPARALLEL;

CREATE UNIQUE INDEX "SCOTT"."PK_EMP" ON "SCOTT"."EMP" ("EMPNO")

PCTFREE 10 INITRANS 2 MAXTRANS 255

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "USERS" PARALLEL 1 ;

ALTER INDEX "SCOTT"."PK_EMP" NOPARALLEL;

如果没有并行设置,索引在之后还要设置上noparallel

7、组件约束设置

索引创建之后,创建约束对象,包括主键关系。

-- new object type path: SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT

-- CONNECT SYS

ALTER TABLE "SCOTT"."DEPT" ADD CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO")

USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "USERS" ENABLE;

ALTER TABLE "SCOTT"."EMP" ADD CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO")

USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "USERS" ENABLE;

8Index统计量"导入"

Oracle Data Pump在导入的时候,是连带将统计量"导入"进去。虽然Oracle可以选择数据表数据插入之后,现去收集统计量,但是还是选择将统计量导入进去。

首先Data Pump导入索引的统计量。

-- new object type path: SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS

DECLARE I_N VARCHAR2(60);

I_O VARCHAR2(60);

c DBMS_METADATA.T_VAR_COLL;

df varchar2(21) := 'YYYY-MM-DD:HH24:MI:SS';

BEGIN

DELETE FROM "SYS"."IMPDP_STATS";

i_n := 'PK_DEPT';

i_o := 'SCOTT';

INSERT INTO "SYS"."IMPDP_STATS" (type,version,flags,c1,c2,c3,c5,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,d1,cl1) VALUES ('I',5,2,I_N,NULL,NULL,I_O,4,1,4,1,1,1,0,4,NULL,NULL,NULL,NULL,TO_DATE('2012-06-23 01:37:56',df),NULL);

DBMS_STATS.IMPORT_INDEX_STATS('"' || i_o || '"','"' || i_n || '"',NULL,'"IMPDP_STATS"',NULL,'"SYS"');

DELETE FROM "SYS"."IMPDP_STATS";

END;

/

上面是一个PL/SQL匿名块。Oracle导入导出一个统计量,都是需要一个中间数据表。在这个过程中,我们看到了Oracle用一个sys.impdp_stats数据表。先将其清空,之后插入一条数据。最后调用dbms_stats.import_index_stats方法将数据表导入到系统中。

Impdp_stats数据表是Oracle内部的一个工具表。

SQL> desc impdp_stats;

Name Type Nullable Default Comments

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

STATID VARCHAR2(30) Y

TYPE CHAR(1) Y

VERSION NUMBER Y

FLAGS NUMBER Y

(篇幅原因,有省略……

每一个索引对应一个PL/SQL匿名块。

9、视图View对象创建

创建Index统计量之后,创建视图view对象。

-- new object type path: SCHEMA_EXPORT/VIEW/VIEW

-- CONNECT SCOTT

CREATE FORCE VIEW "SCOTT"."XX" ("OWNER", "OBJECT_NAME", "SUBOBJECT_NAME", "OBJECT_ID", "DATA_OBJECT_ID", "OBJECT_TYPE", "CREATED", "LAST_DDL_TIME", "TIMESTAMP", "STATUS", "TEMPORARY", "GENERATED", "SECONDARY", "NAMESPACE", "EDITION_NAME") AS

select "OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAMP","STATUS","TEMPORARY","GENERATED","SECONDARY","NAMESPACE","EDITION_NAME" from m

;

10、外键约束关系

外键关系在视图之后进行创建。

-- new object type path: SCHEMA_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT

-- CONNECT SYS

ALTER TABLE "SCOTT"."EMP" ADD CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO")

REFERENCES "SCOTT"."DEPT" ("DEPTNO") ENABLE;

ALTER TABLE "SCOTT"."T_CHILD2" ADD CONSTRAINT "FK_CHILD2_MASTER" FOREIGN KEY ("MID")

REFERENCES "SCOTT"."T_MASTER" ("ID") ENABLE;

外键创建之后,就直接启用。注意如果数据量很大,并且前期索引关系没有设置好,这个过程可能持续时间很长。

11、数据表统计量导入

之后是数据表统计量的导入。和索引不同的是,一个数据表统计量是通过多条impdp_stats记录来完成。从下面分别从数据表和字段信息来进行导入。

-- new object type path: SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS

DECLARE

c varchar2(60);

nv varchar2(1);

df varchar2(21) := 'YYYY-MM-DD:HH24:MI:SS';

s varchar2(60) := 'SCOTT';

t varchar2(60) := 'DEPT';

p varchar2(1);

sp varchar2(1);

stmt varchar2(300) := 'INSERT INTO "SYS"."IMPDP_STATS" (type,version,c1,c2,c3,c4,c5,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,d1,r1,r2,ch2,flags) VALUES (''C'',5,:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19,:20,:21)';

BEGIN

DELETE FROM "SYS"."IMPDP_STATS";

INSERT INTO "SYS"."IMPDP_STATS" (type,version,flags,c1,c2,c3,c5,n1,n2,n3,n4,n10,n11,n12,d1) VALUES ('T',5,2,t,p,sp,s,

4,5,20,4,NULL,NULL,NULL,

TO_DATE('2012-06-23 01:37:56',df));

c := 'DEPTNO';

EXECUTE IMMEDIATE stmt USING t,p,sp,c,s,

4,.25,4,4,0,10,40,3,nv,nv,nv,

TO_DATE('2012-06-23 01:37:56',df),'C10B','C129',nv,2;

c := 'DNAME';

EXECUTE IMMEDIATE stmt USING t,p,sp,c,s,

4,.25,4,4,0,3.38863550087541E+35,4.32285038677786E+35,10,nv,nv,nv,

TO_DATE('2012-06-23 01:37:56',df),'4143434F554E54494E47','53414C4553',nv,2;

c := 'LOC';

EXECUTE IMMEDIATE stmt USING t,p,sp,c,s,

4,.25,4,4,0,3.44300505052090E+35,4.06405544089997E+35,8,nv,nv,nv,

TO_DATE('2012-06-23 01:37:56',df),'424F53544F4E','4E455720594F524B',nv,2;

DBMS_STATS.IMPORT_TABLE_STATS('"SCOTT"','"DEPT"',NULL,'"IMPDP_STATS"',NULL,NULL,'"SYS"');

DELETE FROM "SYS"."IMPDP_STATS";

END;

/

和索引不一样的,由于数据表column数量不一样,一个PL/SQL匿名块只导入几个column统计量。如果column数目多,可能会拆成多个匿名块。

我们思考一个统计量问题:Oracle明明可以重新收集一下统计量,为什么还要将统计量数据保存在DMP文件里面占据空间。并且在数据之后导入到其中。

笔者认为这个是Oracle从两个方面考量:

首先是时间上,如果数据表很大、结构复杂,收集一次统计量的时间是比较长的。也就是说,统计量获取的过程和数据表大小有关系。而数据统计量导入的动作,各个数据持续时间没有什么差别。想必这个是Oracle的一个综合考虑。

另外,从执行计划CBO生成的角度看,"导入"统计量也是有其合理性。有时候我们可能需要固定统计量,也就是希望数据统计量不要"及时更新",从而固化执行计划。

12、结论

Oracle Datapump生成的SQLFILE可以帮助我们了解其运行细节。

数据 统计 数据表 索引 用户 对象 权限 过程 空间 文件 方法 时间 生成 语句 问题 也就是 事件 信息 参数 结构 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全审计中 数据库结构 三大范式 城阳区app软件开发公司 北京电费缴费软件开发团队 安卓应用软件开发应聘 网络安全的七层 小型公司服务器好吗 如何成为网络安全创业者 南京天象网络技术有限分公司 大学网络技术与应用重要么 数据库怎么查最后10条 软件开发二次合同范本 网络安全是一门涉及哪些学科 关闭服务器代理 档案馆网络安全自查工作方案 单选题每个数据库有且只有一个 电脑服务器交换机的连接 软件开发大龄程序员 网络安全法实施后处罚案例 贵州智能土地gis系统软件开发 有什么警校文科能报网络安全 服务器提高内存和cpu占用率 阿里服务器登陆 河北通讯软件开发服务价钱 安卓应用软件开发应聘 内蒙古定制网络技术服务哪个正规 网络安全工作实施总结反馈 单选题每个数据库有且只有一个 全国软件开发工资 易晟源集团软件开发公司
0