对于Oracle的数据导出和导入,我们之前一直使用exp、imp来处理, 但用imp在导入时经常会要求表空间一致,而博主今天恰恰就遇到了需要变更表空间和用户的情况,这在我们平常的业务场景中也会遇到,那么该如何处理呢?
我们采用Oralce的 “数据泵” Data Dump来处理。
测试环境:Windows Server 2008 R2、Oracle11g
1、数据泵(Data Dump)主要解决问题
2、数据泵使用限制
3、创建测试数据库
4、导出源数据库
5、导入目标数据库
6、验证导入后表空间
①. 比imp/exp更加灵活,支持多种元数据过滤策略,多种导入、导出模式,如将A表空间B用户数据导入C表空间D用户下,则只需REMAP_SCHEMA即可
②. 表空间占用和表空间变更问题,可使用REMAP_TABLESPACE来解决
③. 空表问题,Oracle11g新的表并且表中无数据也为使用过则表的segment空间是不会分配的,这样在使用exp导出时空表便不会被导出,解决这个问题要么给空分配segment或直接使用expdp。
④. 效率问题。普通情况下expdp/impdp比exp/imp效率要高,高多少博主没有测试,有兴趣的不妨验证下,@博主。
使用expdp、impdp有条件限制
一是远程使用时必须配置好Database Link,因为expdp、impdp只能在服务端使用,不能再客户端使用;
二是试用前要解决路径配置问题。
创建源用户和表空间,为了便于操作我们给新创建用户授权的了dba权限,大家在本地使用时注意
/*第1步:创建临时表空间 */
create temporary tablespace test_source_temp
tempfile 'D:\Oracle11g\oradata\test_source_temp.dbf'
size 10m
autoextend on
next 1m maxsize unlimited
extent management local;
/*第2步:创建数据表空间 */
create tablespace test_source
logging
datafile 'D:\Oracle11g\oradata\test_source.dbf'
size 10m
autoextend on
next 1m maxsize unlimited
extent management local;
/*第3步:创建用户并指定表空间 */
create user test_source identified by a123456
default tablespace test_source
temporary tablespace test_source_temp;
/*第4步:给用户授予权限 */
grant connect,resource,dba to test_source;
创建两张测试表,一张基础数据类型,一张含clob、blob、date等复杂数据类型
--表1
create table tab_1
(
tab1_field1 number,
tab1_field2 varchar2(20),
tab1_field3 varchar2(10)
)
--插入测试数据
insert into TAB_1 (tab1_field1, tab1_field2, tab1_field3) values (1, 'a12', 'a13');
insert into TAB_1 (tab1_field1, tab1_field2, tab1_field3) values (2, '张22', '李23');
--表2
create table TAB_2
(
tab2_field1 NUMBER,
tab2_field2 VARCHAR2(20),
tab2_field3 DATE,
tab2_field4 CLOB,
tab2_field5 BLOB
)
--插入测试数据
insert into TAB_2 (tab2_field1,tab2_field2,tab2_field3,tab2_field4,tab2_field5) values ('1','A12',SYSDATE,'测试1','C1');
insert into TAB_2 (tab2_field1,tab2_field2,tab2_field3,tab2_field4,tab2_field5) values ('1','测试22',SYSDATE,'测试2','C2');
insert into TAB_2 (tab2_field1,tab2_field2,tab2_field3,tab2_field4,tab2_field5) values ('1','嘿嘿32',SYSDATE,'测试3','C3');
创建目标用户和表空间
/*第1步:创建临时表空间 */
create temporary tablespace test_target_temp
tempfile 'D:\Oracle11g\oradata\test_target_temp.dbf'
size 10m
autoextend on
next 1m maxsize unlimited
extent management local;
/*第2步:创建数据表空间 */
create tablespace test_target
logging
datafile 'D:\Oracle11g\oradata\test_target.dbf'
size 10m
autoextend on
next 1m maxsize unlimited
extent management local;
/*第3步:创建用户并指定表空间 */
create user test_target identified by a123456
default tablespace test_target
temporary tablespace test_target_temp;
/*第4步:给用户授予权限 */
grant connect,resource,dba to test_target;
这里需要注意:
EXP和IMP是客户端工具程序,它们既可以在客户端使用,也可以在服务端使用。
而EXPDP和IMPDP是服务端的工具程序,他们只能在ORACLE服务端使用,不能在客户端使用。
IMP只适用于EXP导出的文件,不适用于EXPDP导出文件;IMPDP只适用于EXPDP导出的文件,而不适用于EXP导出文件。
我们这里需要使用expdp导出,需在服务端执行。
①.创建逻辑目录
--创建一个dump路径的对象
create directory dump_dir1 AS 'D:\Oracle11g\admin\orcl\dpdump';
当然我们这里也可以使用dump默认目录,查询默认目录,然后执行创建
--查询使用默认dump路径
select * from dba_directories where directory_name='DATA_PUMP_DIR';
--创建一个dump路径的对象
create directory dump_dir1 AS 'D:\Oracle11g\admin\orcl\dpdump';
--查询已创建的dump路径对象
select * from dba_directories where directory_name='DUMP_DIR1';
但正常情况下这个目录只有dba 和system高级用户可以使用,所以我们需要给用户授权,这里我们同时给源数据库用户和目标数据库用户均加上目录授权。
--用户地址读写授权
grant read,write on directory dump_dir1 to test_source;
grant read,write on directory dump_dir1 to test_target;
②.导出源数据库
在数据库服务器上,点击Win+R弹出命令框,输入“cmd”,进入命令操作框,输入以下语句,导出数据文件dmp。
1)按用户导
expdp test_source/a123456 directory=dump_dir1 dumpfile=test_source.dmp schemas=test_source;
2)并行进程parallel
expdp test_source/a123456 directory=dump_dir1 dumpfile=test_source.dmp parallel=40 job_name=test_source
3)按表名导
expdp test_source/a123456 directory=dump_dir1 dumpfile=test_source.dmp tables=tab_1,tab_2;
4)按查询条件导
expdp test_source/a123456 directory=dump_dir1 dumpfile=test_source.dmp tables=tab_1 query='where deptno=20';
5)按表空间导
expdp test_source/a123456 directory=dump_dir1 dumpfile=test_source.dmp tablespaces=test_source;
6)导整个数据库
expdp test_source/a123456 directory=dump_dir1 dumpfile=test_source.dmp full=y;
我采用按用户导出测试,发现报以下错误
然后打开目录“”发现该目录为只读目录,去掉只读选项,确认,同时增加日志文件指向
再次尝试,成功!
上面我们已经给目标数据库用户加上了目录授权,可以通过下面语句进行导入:
1)导到指定用户下
impdp test_target/a123456 directory=dump_dir1 dumpfile=test_source.dmp schemas=test_target;
2)改变表的owner
impdp test_target/a123456 directory=dump_dir1 dumpfile=test_source.dmp tables=test_target.tab_1,test_target.tab_2 remap_schema=test_target;
3)导入表空间
impdp test_target/a123456 directory=dump_dir1 dumpfile=test_source.dmp tablespaces=test_target;
4)导入数据库
impdb test_target/a123456 directory=dump_dir1 dumpfile=test_source.dmp full=y;
5)追加数据
impdp test_target/a123456 directory=dump_dir1 dumpfile=test_source.dmp schemas=test_target table_exists_action
我们采用导入指定用户下,同时改变他的owner和表空间
impdp test_target/a123456 directory=dump_dir1 dumpfile=test_source.dmp remap_schema=test_source:test_target
remap_tablespace=test_source:test_target
导入完成!
我们验证下导入后的表所属用户和表空间是否有变化
所属用户和表空间已发生改变。
为了确保blob、clob等字段所属表空间已改变,我们删除源数据库用户和表空间,测试目标数据库是否正常
--删除源数据库用户
drop user test_source;
--因为所删表空间非空,所以我们加上including contents进行表空间删除
drop tablespace test_source including contents and datafiles;
然后我们查询下带有clob和blob字段的表数据是否正常
成功,完美!