[原]使用可传输表空间修改Schema Name
我同学 Frank 尝试通过修改数据字典表来达到修改 Schema Name 的目的,但是引出了一大堆问题,详看这两博客:
Change Schema Name & ORA-01031: insufficient privileges (on SYS.DMBS_SESSION), ORA-28100, etc...
以往我会通过 exp/imp 或者 expdp/impdp 完成类似的数据迁移,但是如果数量比较大,导出的可能性比较低,如果仅为修改一个Schema Name 而去导入导出2~3T的数据,那简直就是又一出“一个馒头引发的血案”。
考虑到以上问题,我尝试使用可传输表空间来完成这项任务。
创建测试环境
为 frank 建立用户和相应的表空间:
create tablespace frank datafile '/u02/oradata/ora10g/ORA10G/ora10g/frank01.dbf' size 20M autoextend on logging segment space management auto extent management local; create user frank identified by frank default tablespace frank; grant connect to frank; grant resource to frank; revoke unlimited tablespace from frank; alter user frank quota unlimited on frank;
使用用户 frank 进行登录,然后创建一些对象,例如表 objects :
create table objects as select * from all_objects insert into objects select * from objects ; insert into objects select * from objects ; insert into objects select * from objects ; insert into objects select * from objects ; commit;
现在 objects 这个表有“很多很多”数据,移动起来“非常非常”困难,但我又必须修改 frank 这个 Schema Name 为 killkill
导出成可传输表空间
我选用数据泵配合可传输表空间,所以需要创建一个 directory 出来:
create or replace directory DATAPUMP as '/home/ora10g/datapump'; grant read,write on directory DATAPUMP to public ;
将表空间 frank 设为只读:
alter tablespace frank read only;
在命令行将表空间 frank “导出”,其实是导出数据字典,这个文件很小。
expdp system/oracle dumpfile=expdp_frank.dmp directory=datapump transport_tablespaces=frank
清理旧的Schema
将表空 frank offline :
alter tablespace frank offline ;
然后将数据文件改名,以适应新的表空间命名规范,在命令行中执行:
cd /u02/oradata/ora10g/ORA10G/ora10g/ mv ./frank01.dbf ./killkill01.dbf
清理 Frank,我比较狠,关于Frank 的东西全部干掉:
drop user frank cascade; drop tablespace frank including contents;
从可传输表空间导入
首先,要为新的 Schema 建一个用户,就叫 killkill 吧:
create user killkill identified by killkill; grant connect to killkill; grant resource to killkill;
我们稍后再为 killkill 指定默认表空间。
在命令行中导入:
impdp system/oracle DUMPFILE=expdp_frank.dmp DIRECTORY=DATAPUMP \ TRANSPORT_DATAFILES=/u02/oradata/ora10g/ORA10G/ora10g/killkill01.dbf \ REMAP_SCHEMA=(frank:killkill) \ REMAP_TABLESPACE=(frank:killkill)
注意,REMAP_SCHEMA 就是修改 Schema Name 的关键,顺便将表空间的名字也改过来(REMAP_TABLESPACE)。
导入完毕,将新导入的表空间 killkill 设为 read write 模式,并设定为用户 killkill 的默认表空间:
alter tablespace killkill read write ; alter user killkill default tablespace killkill ;
登录验收
这个就很简单了:
connect killkill/killkill select count(*) from objects;
小结
回顾整个过程,我们所需的磁盘空间实际上就是导出 expdp_frank.dmp 的文件大小,本次实验,该文件大小为 80K ,非常小;将数据文件改名,只要不是夸文件系统的移动,那几乎就是不需要时间和I/O的;导入可传输表空间,也就是导入那个80K的文件,即使普通的PC机也不是什么难事。
虽然整个过程比较繁琐,但是基本不会出错。
但是话说回来,如果用户 Frank 有几个Schema,所有 Schema 都放在一个表空间中,那么就不能用这个方法了。