Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1026830
  • 博文数量: 171
  • 博客积分: 55
  • 博客等级: 民兵
  • 技术积分: 2077
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-04 10:11
个人简介

pugna

文章分类

全部博文(171)

文章存档

2021年(4)

2020年(1)

2019年(4)

2018年(5)

2017年(7)

2016年(9)

2015年(36)

2014年(8)

2013年(96)

2012年(1)

分类: Oracle

2013-08-05 15:08:31

今天要把一个db_1上某个用户的表结构迁移到另一个db_2上,两者的用户名要保持相同,表空间也必须相同。



先说下我尝试过的方法:
1.使用下面的脚本通过dbms_metadata.get_ddl过程直接获取test用户所有表的DDL语句。
set long 100000 linesize 130 pagesize 1000                                                                                                  
col schema_ddl for a1000                                                                                                                         
spool schema_ddl.txt
select replace(to_char(dbms_lob.substr(dbms_metadata.get_ddl('TABLE',table_name,'TEST'), 4000, 1)),'"','')||';' schema_ddl  from dba_tables  WHERE owner='TEST';
spool off
但是,你看到脚本中的dbms_lob.substr()就发现了,有些表(分区表,特别是那些有n个分区的分区表)的DDL语句就毫不犹豫地超过了4000个字符,所以,这个方法经过简单测试后因不实用而放弃。不过,好像dbms_metadata.get_ddl()有个参数可以把storage那些信息不输出,我懒得测试了,不知道具体效果如何。试验过的朋友记得留言告诉我下。



2.使用exp/imp进行只导schema定义
导出使用以下脚本(direct=y 表示使用直接路径, rows=n 表示不导出数据,只导定义; 而且还发现exp所使用的用户不能使用sysdba角色)
exp test/test direct=y rows=n file=/oracle/test_schema_20130802.dmp owner=test log=/oracle/exp.log
导入使用以下脚本(buffer=20480000 一定要加上,否则可能报错)
imp test/test buffer=20480000 ignore=y  fromuser=test touser=test file=/oracle/test_schema_20130802.dmp log=/oracle/imp.log

经过实验测试,exp耗时5分钟左右,导出的文件大小为100M,而imp的时候就蛋疼了,耗时2小时才导入完成,而且还报一堆错。报错也就算了,还莫名其妙地把一个tablespace搞得在dba_free_space视图中查询不到了,v$tablespace中却还可以看到。被搞伤了,果断换方案!



3.最后决定使用expdp/impdp来完成

前期准备工作,在db_2上建立相应的表空间,建立相应的test用户,然后授予test用户在各表空间的磁盘配额。

create tablespace ts_work
logging
datafile '/oradata/ts_work01.dbf'
size 2g
autoextend on
next 2g maxsize 30g
extent management local;

--重做时,使用下面的语句删除表空间
--drop tablespace ts_work including contents and datafiles cascade constraints;

create user test
default tablespace ts_work
identified by "test";

grant unlimited tablespace to test;



使用expdp/impdp方式来导出和导入表结构(其实也包括其它object的定义),具体步骤如下:

--建立directory并授权
create directory dump_file as '/oracle/datapump';
grant read,write on directory dump_file to test;

--编辑参数文件
$ vi expdp_test.par
DIRECTORY=DUMP_FILE --datapump所使用的目录
DUMPFILE=expdp_test_ddl.dmp --expdp数据文件
LOGFILE=expdp_test_ddl.log --expdp日志文件
schemas=test --只导出这个表空间的对象
CONTENT=METADATA_ONLY --只导出各类object的定义


--导出
$ expdp test/test PARALLEL=2 parfile=expdp_test.par

--收回权限
revoke read,write on directory dump_file from test;



--复制expdp_test_ddl.dmp文件
scp

--建立directory并授权
create directory dump_file as '/oracle/datapump';
grant read,write on directory dump_file to test;

--导入
$ impdp test/test PARALLEL=2 directory=dump_file dumpfile=expdp_test_ddl.dmp logfile=impdp_test_ddl.log table_exists_action=replace

--收回权限
revoke read,write on directory dump_file from test;

在db_1上进行expdp及db_2上进行impdp操作时,可以通过以下SQL语句查询expdp/impdp的进度
SELECT owner_name owr, job_name jbn, operation ope, job_mode jbm, state, degree, attached_sessions atts, datapump_sessions dats
FROM   dba_datapump_jobs;

在db_2上进行impdp操作时,Oracle是报错了的,不过都是小问题,只有3类错误,一是object已经存在(这是因为我之前用其它方法导入过),二是INDEX_STATISTICS导入出错(统计信息而已,impdp之后再重新收集就OK),三是几个job创建失败(也就几个,手动处理呗)。

导入完成后,比对一下两边db的test用户的schema中的table或object数量是否相同。

SQL> select count(*) from dba_tables where owner='TEST';
  COUNT(*)
----------
       317

SQL> select count(*) from dba_objects where owner='TEST';
  COUNT(*)
----------
     19412

手动处理创建失败的job。

最后重新收集统计信息。


使用expdp(PARALLEL=2)耗时3分钟不到,导出的文件大小48M,impdp(PARALLEL=2)耗时还是比较长的,40分钟,不过相比imp好多了。



OK,现在schema的定义迁移完了,下一步就是迁移数据了。初步计划使用procedure来搞,到时候再说了。
阅读(4917) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~