现在得到一个需求,需要把生产环境的多个schema下的表结构复制到测试环境中的一个schema下。
生产环境和测试i环境的表空间配置都不一样。
目前可以考虑用如下的几种方式来实现。
1)使用exp/imp来做表结构的导出导入。
2)使用dbms_metadata.get_ddl来生成对应的ddl语句。
3)使用expdp/impdp来做表结构的导入导出。
因为涉及的表大约有2000个,采用dbms_metadata是一个很大的工作量而且在多个schema中需要权衡,所以没有采用。
expdp需要在服务端配置directory,客户要求只能在备库上做导出,备库是在read only状态下的,所以一下子切断了使用expdp的希望。
最后只能使用传统的exp/imp来做了,根据我的经验,这方面exp/imp的速度一点也不逊色。
exp prod_user1/prod_user1 file=prod_user1.dmp buffer=9102000 log=prod_user1.log statistics=none indexes=y constraints=y grants=n rows=n
exp prod_user3/prod_user2 file=prod_user2.dmp buffer=9102000 log=prod_user2.log statistics=none indexes=y constraints=y grants=n rows=n
exp prod_user3/prod_user3 file=prod_user3.dmp buffer=9102000 log=prod_user3.log statistics=none indexes=y constraints=y grants=n rows=n
导出很快就做完了,然后压缩打包,看起来很顺利。
在尝试导入的时候,发现tablespace不匹配,因为测试环境和生产环境的表空间不同,而且因为lob字段的原因,会固执的去找原来的表空间。这个时候就想起来impdp的remap_tablespace的优点了。
但是没法用,最后就临时建了和生产类似的表空间,准备先把表导进去再说,然后再做move的操作,对于move tablespace的时候,需要考虑表和索引,对于表,如果没有lob字段,就可以直接使用move 操作(因为只有表结构没有数据),如果含有lob字段,则需要指定lob列做move操作,对于索引而言move操作就不可用了,需要使用rebuild
如果没有lob字段,表的move操作就不多说了,类似下面的样子,就把表移到了large_data这个表空间里。
alter table xxxx move tablespace large_data;
对于索引,可以采用如下的方式,就索引在large_data中进行了重建。
alter index xxxx rebuild tablespace large_data;
如果表中含有lob字段,则需要指定lob列,lob字段会自动创建数据段,索引段,如果尝试rebuild lob索引时会报如下的错误。
alter index SYS_IL0002310750C00009$$ rebuild tablespace large_data
*
ERROR at line 1:
ORA-02327: cannot create index on expression with datatype LOB
对于lob的地方,多说一些。如果通过数据字典,user_ind_columns来查看,是没有结果的,需要到user_lobs中去查找。
SQL> select index_name,table_name from user_indexes where index_name='SYS_IL0002310750C00009$$';
INDEX_NAME TABLE_NAME
------------------------------ ------------------------------
SYS_IL0002310750C00009$$ APP_XML_CONFIG
SQL> select index_name,column_name from user_ind_columns where index_name='SYS_IL0002310750C00009$$';
no rows selected
select table_name,column_name,tablespace_name,index_name from user_lobs where index_name='SYS_IL0002310750C00009$$'
SQL> /
TABLE_NAME COLUMN_NAME TABLESPACE_NAME INDEX_NAME
------------------------------ ------------------------------ ------------------------------ ------------------------------
APP_XML_CONFIG XML DATAL01 SYS_IL0002310750C00009$$
可以使用下面形式的语句来做lob字段的迁移。
SQL> alter table app_xml_config move tablespace large_data lob(xml) store as lobsegment(tablespace large_data);
Table altered.
对于上千张表来说,使用如下的sql能够自动生成move tablespace的语句。
--对表中的非lob列进行move tablespace操作
select 'alter table '|| table_name||' move tablespace large_data;' from user_tables t where tablespace_name!='LARGE_DATA' and exists ( select null from user_tab_cols where table_name=t.table_name and data_type not in ('LONG','BLOB','CLOB'));
--对表中的lob 列进行move tablespace操作
select 'alter table '||table_name||' move tablespace large_data lob('||column_name||') store as '||SEGMENT_NAME||'(tablespace large_data);' from user_lobs where index_name in (select index_name from user_indexes where tablespace_name!='LARGE_DATA');
--对表中的索引进行rebuild,因为lob数据段已经做了move 操作,对于索引lob段就不用再做move 操作了。
select 'alter index '||index_name||' rebuild tablespace large_data;' from user_indexes where tablespace_name!='LARGE_DATA';