据说是从ORACLE8.16 开始,ORACLE开始支持通过拷贝部分数据文件的方法做数据的迁移,也就是大家常常说到的“ 表空间传输”,尽管在日常用到的不是很多,这里也设计了一个实验,实验内容也比较简单,如果你正好有这方面的工作要做,不妨来参考下本文。
ORACLE从9i 起支持非标准的数据块,DBA可以创建一个或多个数据块大小不为 db_block_size 的表空间,这类表空间会有不同的用途,比如专门用来存放LOB字段,以提高IO的性能,有OCP的教程中提到,非标准的数据块就是为不同的块大小的库之间做“表空间传输”准备的,也有一定的道理。
基于以上的描述,本实验将传输一个相同的块大小的表间及一个不同的块大小的表空间,本实验的局限性:要求两个数据库的字符集一致,操作系统一致,数据版本一致。
具体的实验环境为:
源环境:
OS:Windows 2003 DB:Oracle 9.2.0.7.0 SID:MSGDE db_block_size = 8K
目标环境 :
OS:Windows 2003 DB:Oracle 9.2.0.7.0 SID:PROD db_block_size = 8K
大体的过程是分成两步,一步是导出(备份),二步是导入(恢复)
第一:在源环境上做以下工作(7步)
C:\>set oracle_sid=msgde
1)确认数据库的db_block_size , SID
这里的默认块大小(db_block_size)为 8192=8k ;
| SQL> show parameter db_block_size ; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ SQL> select instance_name from v$instance ; INSTANCE_NAME ---------------- msgde db_block_size integer 8192 |
2)建立非标准块的cache,这里暂时建一个块大小为16k 的表空间,建立之前,先设置一下参数,db_16k_cache_size , 这个参数不能动态的修改,先修改下spfile ,再重启实例生效的,下面列出来了整过程:
| SQL> alter system set db_16k_cache_size=32M ; alter system set db_16k_cache_size=32M * ERROR 位于第 1 行: ORA-02097: 无法修改参数,因为指定的值无效 ORA-00384: 没有足够的内存来增加高速缓存的大小 SQL> alter system set db_16k_cache_size=32M scope=spfile ; 系统已更改。 SQL> shutdown immediate ; 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 SQL> startup ; ORACLE 例程已经启动。 Total System Global Area 403775652 bytes Fixed Size 454820 bytes Variable Size 343932928 bytes Database Buffers 58720256 bytes Redo Buffers 667648 bytes 数据库装载完毕。 数据库已经打开。 SQL> |
3)这一步我们要创建两个表空间,一个为标准数据块(8192),一个为非标准数据(16k),分别建立两个用户默认到这两个表空间上,并分别建立数据表;
表空间已创建。 SQL> create tablespace ts8k datafile 'c:\ts8k.dbf' size 1m blocksize 8k ; 表空间已创建。 SQL> create user u16k identified by oracle default tablespace ts16k ; 用户已创建 SQL> create user u8k identified by oracle default tablespace ts8k ; 用户已创建 SQL> grant resource to u16k ; 授权成功。 SQL> grant resource to u8k ; 授权成功。 SQL> create table u16k.test as select 'this blocksize is 16K' name from dual ; 表已创建。 SQL> create table u8k.test as select 'this blocksize is 8K' name from dual ; 表已创建。 SQL>
4)检查表空间是否自包含,这一步不能省略,否则在imp时可能不会成功:
SQL> exec dbms_tts.transport_set_check('ts16k',true) ; PL/SQL 过程已成功完成。 SQL> exec dbms_tts.transport_set_check('ts8k',true) ; PL/SQL 过程已成功完成。 SQL> select * from transport_set_violations ;
5)将两个表空间只读(read only),这段不难理解,避免在传传输过程中,有人改变数据;:
SQL> alter tablespace ts16k read only ; 表空间已更改。 SQL> alter tablespace ts8k read only ; 表空间已更改。 SQL>
6)生成文件,OS的 exp 命令导出相关文件,这里贴出全部导出日志
C:\>exp userid='sys/oracle as sysdba' file=c:\trans.dmp transport_tablespace=y tablespaces=(ts16k,ts8k) Export: Release 9.2.0.7.0 - Production on 星期二 8月 16 12:58:24 2011 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 连接到: Oracle9i Enterprise Edition Release 9.2.0.7.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.7.0 - Production 已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集 注: 将不会导出表数据(行) 关于导出可传输的表空间元数据... 用于表空间 TS16K... . 正在导出群集定义 . 正在导出表定义 . . 正在导出表 TEST 用于表空间 TS8K... . 正在导出群集定义 . 正在导出表定义 . . 正在导出表 TEST . 正在导出引用完整性约束条件 . 正在导出触发器 . 结束导出可传输的表空间元数据 在没有警告的情况下成功终止导出。 C:\>
7)拷走刚才的 trans.dmp 和 ts16k.dbf 、ts8k.dbf 三个文件;
8)把这两个表空间置为只读,也可以直接删掉。
SQL> alter tablespace ts16k read write ; 表空间已更改。 SQL> alter tablespace ts8k read write ; 表空间已更改。
到此,导出的工作就算完成了;
第二大步,就是导入新的环境中了;
C:\>set oracle_sid=prod
1)确认数据库的db_block_size , SID
SQL> show parameter db_block_size ; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_block_size integer 8192 这里的默认块大小(db_block_size)为 8192=8k ; SQL> select instance_name from v$instance ; INSTANCE_NAME ---------------- prod
2)建立非标准块的cache,这里仅仅贴出一部分内容:
SQL> shutdown immediate ; SQL> startup; SQL>
3)建立用户信息:
SQL> create user u16k identified by oracle default tablespace ts16k ; 用户已创建 SQL> create user u8k identified by oracle default tablespace ts8k ; 用户已创建
4)导入数据
C:\>imp userid='sys/oracle as sysdba' file=c:\trans.dmp transport_tablespace=y tablespaces=(ts16k,ts8k) tts_owners=(u16k,u8k) datafiles=(ts16k.dbf,ts8k.dbf) C:\>
5) 测试一下,看看数据是否存在 ;
SQL> select * from u8k.test ; NAME -------------------- this blocksize is 8K SQL> select * from u16k.test ; NAME --------------------- this blocksize is 16K
此时算是搞定!