关于传输表空间可以参考笔者的这篇文章
http://czmmiao.iteye.com/blog/1260792
当一个Little Endian的系统试图从一个Big Endian的系统中读取数据时,就需要通过转换,否则不同的字节顺序将导致数据不能被正确读取。那么另外一个问题出现了,如果字节序相同的不同平台进行文件交互,数据能否被正确读取呢 ?
理论上的确是可以的,但是由于在不同的平台上操作系统会在数据文件头写上系统信息,这部分信息无法跨越平台,所以仍然会导致跨平台的文件无法被数据库正确识别(Oracle10g中同字节序平台数据文件头不再存在跨平台的迁移问题)。
接下来让我们通过Windows和Linux平台来进行一个跨平台测试,相信通过这个测试可以对以上提出的问题作出一个很好的回答。
实验环境:Windows XP + Oracle10g 10.2.0.1:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
Red Hat Enterprise Linux AS release 3 + Oracle 9iR2 9.2.0.4
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for Linux: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production
看一下Linux平台,文件头被操作系统保留了8192字节:
SQL> select file_name,bytes from dba_data_files
2 where tablespace_name='USERS';
FILE_NAME BYTES
----------------------------------- ----------
/opt/oracle/oradata/eygle/users.dbf 10485760SQL> !
[oracle@jumper eygle]$ ll users.dbf
-rw-r----- 1 oracle dba 10493952 Mar 23 10:14 users.dbf
[oracle@jumper eygle]$ exit
exitSQL> select 10493952 -10485760 diff from dual;
DIFF
----------
8192
Windows平台上数据文件头同样保留了8192字节:
SQL> select file_name,bytes from dba_data_files
2 where tablespace_name='USERS';
FILE_NAME BYTES
--------------------------------------------------- ----------
D:\ORADATA\EYGLE\DATAFILE\O1_MF_USERS_2G8OJYYS_.DBF 5242880SQL> host dir D:\ORADATA\EYGLE\DATAFILE\O1_MF_USERS_2G8OJYYS_.DBF
驱动器 D 中的卷是 PRIVAT
卷的序列号是 94B0-FD3BD:\ORADATA\EYGLE\DATAFILE 的目录
2007-03-22 17:41 5,251,072 O1_MF_USERS_2G8OJYYS_.DBF
1 个文件 5,251,072 字节
0 个目录 1,635,913,728 可用字节
SQL> select 5251072 -5242880 diff from dual;
DIFF
----------
8192
可以通过Linux和Windows平台来进行一个小测试实验,这两个平台都是Little Endian的系统:
SQL> select * from v$transportable_platform;PLATFORM_ID PLATFORM_NAME ENDIAN_FORMAT
----------- ---------------------------------------- --------------
1 Solaris[tm] OE (32-bit) Big
2 Solaris[tm] OE (64-bit) Big
7 Microsoft Windows IA (32-bit) Little
10 Linux IA (32-bit) Little
............
17 rows selected.
首先在Linux下Oracle 9204中创建一个测试表空间:
[oracle@jumper oracle]$ cd oradata/eygle
[oracle@jumper eygle]$ sqlplus "/ as sysdba"
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning option
JServer Release 9.2.0.4.0 - ProductionSQL> create tablespace eyglee datafile size 10M;
Tablespace created.
创建测试用户并创建一个测试表:
SQL> create user eyglee identified by eyglee default tablespace eyglee;
User created.SQL> grant connect,resource to eyglee;
Grant succeeded.SQL> connect eyglee/eyglee
Connected.
SQL> create table eyglee as select * from dict;
Table created.SQL> select count(*) from eyglee;
COUNT(*)
----------
477
将表空间设置为只读:
SQL> connect / as sysdba
Connected.SQL> alter tablespace eyglee read only;
Tablespace altered.SQL> select file_name from dba_data_files where tablespace_name='EYGLEE';
FILE_NAME
------------------------------------------------------------
/opt/oracle/oradata/eygle/o1_mf_eyglee_309yc9gr_.dbf
压缩文件以方便传输:
[oracle@jumper eygle]$ tar -cvf eyglee.tar o1_mf_eyglee_309yc9gr_.dbf
o1_mf_eyglee_309yc9gr_.dbf
[oracle@jumper eygle]$ gzip eyglee.tar
导出表空间:
[oracle@jumper eygle]$ exp \'/ as sysdba\' tablespaces=eyglee transport_tablespace=y file=trans_eyglee.dmpExport: Release 9.2.0.4.0 - Production on Sat Mar 24 18:17:32 2007
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.Connected to: Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning option
JServer Release 9.2.0.4.0 - Production
Export done in ZHS16GBK character set and AL16UTF16 NCHAR character set
Note: table data (rows) will not be exported
About to export transportable tablespace metadata...
For tablespace EYGLEE ...
. exporting cluster definitions
. exporting table definitions
. . exporting table EYGLEE
. exporting referential integrity constraints
. exporting triggers
. end transportable tablespace metadata export
Export terminated successfully without warnings.[oracle@jumper eygle]$ ll *eyglee*
-rw-r--r-- 1 oracle dba 32985 Mar 24 18:14 eyglee.tar.gz
-rw-r----- 1 oracle dba 10493952 Mar 24 18:13 o1_mf_eyglee_309yc9gr_.dbf
-rw-r--r-- 1 oracle dba 16384 Mar 24 18:17 trans_eyglee.dmp
传输文件到Windows平台:
D:\oradata\EYGLE\DATAFILE>dir *eyglee*
D:\oradata\EYGLE\DATAFILE 的目录2007-03-24 18:21 32,985 eyglee.tar.gz
2007-03-24 18:21 16,384 trans_eyglee.dmpD:\oradata\EYGLE\DATAFILE>gzip -d eyglee.tar.gz
D:\oradata\EYGLE\DATAFILE>tar -xvf eyglee.tar
tar: blocksize = 20
x o1_mf_eyglee_309yc9gr_.dbf, 10493952 bytes, 20496 tape blocks
在Windows上创建新用户:
SQL> create user eyglee identified by eyglee;
用户已创建。SQL> grant connect ,resource to eyglee;
授权成功。
如果此时导入会出现ORA-00600错误:
D:\oradata\EYGLE\DATAFILE>imp '/ as sysdba' tablespaces=eyglee transport_tablespace=y file=trans_eyglee.dmp datafiles=d:\oradata\EYGLE\DATAFILE\o1_mf_eyglee_309yc9gr_.dbfImport: Release 10.2.0.1.0 - Production on 星期六 3月 24 18:59:23 2007
Copyright (c) 1982, 2005, Oracle. All rights reserved.连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options经由常规路径由 EXPORT:V09.02.00 创建的导出文件
即将导入可传输的表空间元数据...
已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
. 正在将 SYS 的对象导入到 SYS
. 正在将 SYS 的对象导入到 SYS
IMP-00017: 由于 ORACLE 错误 600, 以下语句失败:
"BEGIN sys.dbms_plugts.beginImpTablespace('EYGLEE',9,'SYS',1,0,8192,1,1899"
"6106462,1,2147483645,8,128,8,0,1,0,8,1407686520,1,1,18996106397,NULL,0,0,NU"
"LL,NULL); END;"
IMP-00003: 遇到 ORACLE 错误 600
ORA-00600: 内部错误代码, 参数: [krhcvt_filhdr_v10_01], [], [], [], [], [], [], []
ORA-06512: 在 "SYS.DBMS_PLUGTS", line 1801
ORA-06512: 在 line 1
IMP-00000: 未成功终止导入
其中"参数: [krhcvt_filhdr_v10_01]"提示指文件头无法正确识别。
可以通过对这个文件进行一个特殊操作,为文件更换一个Windows下数据文件的文件头,则数据文件就应该能够被数据库识别。以下是这个"小手术"操作的过程。
首先提取一个Windows数据文件头:
D:\oradata\EYGLE\DATAFILE>dd if=O1_MF_USERS_2G8OJYYS_.DBF of=header.dbf bs=8192 count=1
1+0 records in
1+0 records out
然后去除Linux下的数据文件头:
D:\oradata\EYGLE\DATAFILE>dd if=o1_mf_eyglee_309yc9gr_.dbf of=eyglee.dbf bs=8192 skip=1
1280+0 records in
1280+0 records out
最后将这两个文件合二为一:
D:\oradata\EYGLE\DATAFILE>copy /b header.dbf+eyglee.dbf eygleee.dbf
header.dbf
eyglee.dbf
已复制 1 个文件。
关于在linux下如何分割和合并二进制文件,可以参看笔者的另一篇文章
http://czmmiao.iteye.com/blog/1266577
现在拥有的新文件eygleee.dbf就具有了一个Windows平台的文件头以及Linux下的"文件身"。
至此这个文件就能够被Windows上的Oracle识别了,可以执行导入操作:
D:\oradata\EYGLE\DATAFILE>imp '/ as sysdba' tablespaces=eyglee transport_tablespace=y file=trans_eyglee.dmp datafiles=d:\oradata\EYGLE\DATAFILE\eygleee.dbfImport: Release 10.2.0.1.0 - Production on 星期六 3月 24 19:22:13 2007
Copyright (c) 1982, 2005, Oracle. All rights reserved.连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options经由常规路径由 EXPORT:V09.02.00 创建的导出文件
即将导入可传输的表空间元数据...
已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
. 正在将 SYS 的对象导入到 SYS
. 正在将 SYS 的对象导入到 SYS
. 正在将 EYGLEE 的对象导入到 EYGLEE
. . 正在导入表 "EYGLEE"
成功终止导入, 没有出现警告。
此时数据已经能够被正确识别:
SQL> connect eyglee/eyglee
已连接。
SQL> select count(*) from eyglee;COUNT(*)
----------
477
最后将表空间更改为读写模式,可以进行正常的数据操作:
SQL> connect / as sysdba
已连接。
SQL> alter tablespace eyglee read write;
表空间已更改。
SQL> connect eyglee/eyglee
已连接。
SQL> insert into eyglee select * from eyglee;
已创建477行。
SQL> insert into eyglee select * from eyglee;
已创建954行。
SQL> insert into eyglee select * from eyglee;
已创建1908行。
SQL> commit;
提交完成。
SQL> select count(*) from eyglee;
COUNT(*)
----------
3816
通过这个实验,还可以得出另外一个结论,Oracle 9i的数据文件可以通过表空间传输迁移到Oracle 10g中使用。