将Oracle 数据库中某个用户迁移到另外一个库上,迁移的数据量大小约 120GB 。如果采用 expdp 导出的话时间会很长,再加上导出的 DMP 文件拷贝和 impdp 导入数据的时间,不能满足要求。
这里采用 RMAN 的 CONVERT 功能和 exp/expdp 的 transport_tablespace 的功能。前者将用户所在的表空间的数据文件从一个数据库所在的系统平台中拷贝到另外一个数据库系统上,后者将表空间对应的 metadata 数据拷贝出来。
测试过程虽然顺利,但最后想到一个问题, rman 中的 catalog 记录的 copy 的文件已经被数据库实例占用的情况下,该记录如何删除掉?
后来想到 rman convert 方法,它将文件系统文件拷贝到 ASM 磁盘组,不在 catalog 中留记录。同时,这个方法免去了文件名称修改的操作,更简洁高效。
使用 convert 可以实现跨平台的数据迁移,这点在环境复杂的项目中非常有用。
首先,介绍一下环境。
源库是 redhat linux as 5 ,单数据库实例,文件系统格式保存数据文件,数据库版本为 10.2.0.4 。
目标库是 redhat linux as 5 ,两节点的 RAC , ASM 格式保存数据文件,数据库版本为 10.2.0.4 。
可以使用 SELECT * FROM V$TRANSPORTABLE_PLATFORM; 检查这个版本上的表空间是否支持传输。结果当然是支持的。
其次,了解迁移的表空间和数据对象。
根据 dba_segments 查询到用户使用的哪些表空间,好决定要迁移的表空间。
在表空间确定了以后,如这里是 xxyy 。需要再根据表空间的 segment 都是哪些用户,如果不仅仅是要迁移的用户,还要将新的用户也找出来。
在目标库上提前将这些用户创建好。
这是因为我们采用的是表空间传输迁移数据,所以难免会有多的对象被迁移。根据实际情况权衡,决定是清理源头还是全部迁移。
表空间的 segment 的类型需要先分析一下。对于分区表、 IOT 表、 XMLType 对象等等不常见的,要先想想能不能用它迁移,这是第一点。
还有两点:一,目标库和源库的字符集要一致,否则请测试该方案;二、目标库不能有同名的表空间。
最后,开始正式迁移操作,步骤如下:
第一步,准备工作
校验表空间是否 self contained (注:不知道如何翻译,原文输出)
SQL> execute sys.dbms_tts.transport_set_check('XXYY', true);
SQL> select * from sys.transport_set_violations;
如果有记录,必须处理。
将表空间设置为只读状态。这点好理解,开始迁移了,就不能再写入数据到表空间了。
SQL> ALTER TABLESPACE XXYY READ ONLY;
第二步,使用 exp 导出表空间所有对象的 metadata
exp userid=\'sys/sys as sysdba\' file=tbs_exp.dmp log=tba_exp.log transport_tablespace=y tablespaces=XXYY
第三步,使用 rman 的 convert 将表空间的数据文件拷贝到文件系统上。
确定文件系统的平台名称
SQL> SELECT tp.platform_id,substr(d.PLATFORM_NAME,1,30), ENDIAN_FORMAT
2 FROM V$TRANSPORTABLE_PLATFORM tp, V$DATABASE d
3 WHERE tp.PLATFORM_NAME = d.PLATFORM_NAME;
PLATFORM_ID SUBSTR(D.PLATFORM_NAME,1,30)
----------- ------------------------------------------------------------
ENDIAN_FORMAT
--------------
13 Linux x86 64-bit
Little
根据平台名称,拷贝出文件名称。
convert tablespace xxyy to platform="Linux x86 64-bit" FORMAT '/u01/oradata/servdb/%U';
测试操作过程如下
[oracle@xxtradedb1 servdb]$ rman target /
Recovery Manager: Release 10.2.0.4.0 - Production on Wed Apr 18 13:13:04 2012
Copyrigxx (c) 1982, 2007, Oracle. All rigxxs reserved.
connected to target database: SERVDB (DBID=3658273059)
RMAN> convert tablespace xxyy to platform="Linux x86 64-bit" FORMAT '/u01/oradata/servdb/%U';
Starting backup at 18-APR-12
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: sid=347 devtype=DISK
channel ORA_DISK_1: starting datafile conversion
input datafile fno=00035 name=/u01/oradata/servdb/datafile/xxyy01.dbf
^[converted datafile=/u01/oradata/servdb/data_D-SERVDB_I-3658273059_TS-XXYY_FNO-35_e1n8o3nc
channel ORA_DISK_1: datafile conversion complete, elapsed time: 00:10:55
Finished backup at 18-APR-12
第四步,将文件拷贝到目标库所在的系统上
这里使用 scp ,也可以使用 ftp ,那样会更快。
第五步,在目标库上建用户,导入数据
imp userid=\'sys/sys as sysdba\' file=tbs_exp.dmp log=tba_imp.log transport_tablespace=y datafiles='/dbbackup/servdb_rman/xxyy01.dbf'
第六步,检查表空间状态和调整表空间为读写
虽然目标库是 RAC ,文件又是保存在 ASM 上,但是也不是不能访问文件系统上的文件。
只是文件系统文件无法共享,所以,只能在一个节点上看到。
/dbbackup/servdb_rman@webdg1=>xxzq1$sqlplus / as sysdba
SQL*Plus: Release 10.2.0.4.0 - Production on Wed Apr 18 16:39:56 2012
Copyrigxx (c) 1982, 2007, Oracle. All Rigxxs Reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options
SQL> set linesize 300
SQL> col name format a50
SQL> r
1* select file#,name,status from v$datafile
FILE# NAME STATUS
---------- -------------------------------------------------- -------
1 +LOGDG/xxzq/system01.dbf SYSTEM
2 +LOGDG/xxzq/undotbs01.dbf ONLINE
3 +LOGDG/xxzq/sysaux01.dbf ONLINE
4 +LOGDG/xxzq/users01.dbf ONLINE
5 +LOGDG/xxzq/undotbs02.dbf ONLINE
6 +LOGDG/xxzq/tbs_yy01.dbf ONLINE
7 /dbbackup/servdb_rman/xxyy01.dbf ONLINE
7 rows selected.
这个结果表空间的数据在其他实例上也操作了,将导致系统宕机,因为其他实例根本不能读写到这个系统上的文件。
我们正常将是设置为读写状态。这是为了将文件从文件系统上迁移到 ASM 上。
SQL> alter tablespace xxyy read write;
如果不将表空间设置为读写状态,则对此表空间文件的 COPY 将出错。开始我也没设置为读写,所以报错了。
RMAN> backup as copy datafile '/dbbackup/servdb_rman/xxyy01.dbf' format '+LOGDG/xxzq/xxyy01.dbf';
Starting backup at 18-APR-12
using channel ORA_DISK_1
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of backup command at 04/18/2012 16:45:25
RMAN-20201: datafile not found in the recovery catalog
RMAN-06010: error while looking up datafile: /dbbackup/servdb_rman/xxyy01.dbf
RMAN> exit
设置为读写后,正常将数据文件拷贝一份到了 ASM 上。
backup as copy datafile '/dbbackup/servdb_rman/xxyy01.dbf' format '+LOGDG/xxzq/xxyy01.dbf';
第七步,将文件离线,在重命名就可以了。
SQL> alter database datafile '/dbbackup/servdb_rman/xxyy01.dbf' offline;
Database altered.
SQL> alter database rename file '/dbbackup/servdb_rman/xxyy01.dbf' to '+LOGDG/xxzq/xxyy01.dbf';
Database altered.
SQL> select name from v$datafile;
NAME
--------------------------------------------------------------------------------
+LOGDG/xxzq/system01.dbf
+LOGDG/xxzq/undotbs01.dbf
+LOGDG/xxzq/sysaux01.dbf
+LOGDG/xxzq/users01.dbf
+LOGDG/xxzq/undotbs02.dbf
+LOGDG/xxzq/tbs_yy01.dbf
+LOGDG/xxzq/xxyy01.dbf
7 rows selected.
SQL> alter database datafile 7 online;
alter database datafile 7 online
*
ERROR at line 1:
ORA-01113: file 7 needs media recovery
ORA-01110: data file 7: '+LOGDG/xxzq/xxyy01.dbf'
SQL> recover datafile 7;
Media recovery complete.
SQL> alter database datafile 7 online;
Database altered.
SQL> exit
迁移实际上到这步就结束了。
但最后想到一个问题。
我们将文件使用 copy 拷贝到了 asm 中,然后让实例使用了。
这时, rman 的 catalog 还是认为这个文件是它的一个拷贝,虽然不能删除,但始终是个芥蒂。
/dbbackup/servdb_rman@webdg1=>xxzq1$rman target /
Recovery Manager: Release 10.2.0.4.0 - Production on Wed Apr 18 16:20:36 2012
Copyrigxx (c) 1982, 2007, Oracle. All rigxxs reserved.
connected to target database: XXZQ (DBID=485623294)
RMAN> list copy;
using target database control file instead of recovery catalog
specification does not match any archive log in the recovery catalog
List of Datafile Copies
Key File S Completion Time Ckp SCN Ckp Time Name
------- ---- - --------------- ---------- --------------- ----
3 7 A 18-APR-12 98532714754 18-APR-12 +LOGDG/xxzq/xxyy01.dbf
尝试使用 RMAN 的 switch 作数据文件重命名,但 rman 中还是有这个记录,不能除掉。
RMAN> switch datafile '/dbbackup/servdb_rman/xxyy01.dbf' to copy;
最后,想到一个方法。使用 convert 代替 copy 将数据文件复制到 ASM 中。 convert 操作是不在 catalog 中留记录的。
上面列的操作步骤在第四步之后就进行跳转。
第四步中将文件传输到文件系统中后,使用 rman convert 将文件复制一份到 ASM 磁盘组中。
这个 convert 功能在 rman catalog 中不保留记录,可以实现 ASM 和文件系统的文件相互转移。
方法如下:
convert datafile '/dbbackup/servdb_rman/xxyy01.dbf' format '+LOGDG/xxzq/xxyy01.dbf';
这个文件约 5GB ,所用时间为 35 秒。
RMAN> convert datafile '/dbbackup/servdb_rman/xxyy01.dbf' format '+LOGDG/xxzq/xxyy01.dbf';
Starting backup at 19-APR-12
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: sid=105 instance=xxzq1 devtype=DISK
channel ORA_DISK_1: starting datafile conversion
input filename=/dbbackup/servdb_rman/xxyy01.dbf
converted datafile=+LOGDG/xxzq/xxyy01.dbf
channel ORA_DISK_1: datafile conversion complete, elapsed time: 00:00:35
Finished backup at 19-APR-12
第五步,在目标库上建用户,导入数据
imp userid=\'sys/sys as sysdba\' file=tbs_exp.dmp log=tba_imp.log transport_tablespace=y datafiles='+LOGDG/xxzq/xxyy01.dbf'
这个步骤和上述用的差别就是文件名称的差别。
第六步,检查表空间状态和调整表空间为读写
因为数据文件本身就在 ASM 磁盘组上, RAC 的两个节点都能访问得到该文件,所以我们先查查文件状态。
SQL> set linesize 300
SQL> col name format a50
SQL> r
1* select file#,name,status from v$datafile
FILE# NAME STATUS
---------- -------------------------------------------------- -------
1 +LOGDG/xxzq/system01.dbf SYSTEM
2 +LOGDG/xxzq/undotbs01.dbf ONLINE
3 +LOGDG/xxzq/sysaux01.dbf ONLINE
4 +LOGDG/xxzq/users01.dbf ONLINE
5 +LOGDG/xxzq/undotbs02.dbf ONLINE
6 +LOGDG/xxzq/tbs_yy01.dbf ONLINE
7 +LOGDG/xxzq/xxyy01.dbf ONLINE
7 rows selected.
所有文件都是 ONLINE 的状态。
我们将其设置为读写状态,这样用户就可以读写迁移过来的表空间中的所有对象了。
SQL> alter tablespace xxyy read write;
我们回到 RMAN 中,使用 list copy 检查一下文件有没有拷贝记录。
/u01/oracle/home@webdg1=>xxzq1$rman target /
Recovery Manager: Release 10.2.0.4.0 - Production on Thu Apr 19 09:46:23 2012
Copyrigxx (c) 1982, 2007, Oracle. All rigxxs reserved.
connected to target database: XXZQ (DBID=485623294)
RMAN> list copy;
using target database control file instead of recovery catalog
specification does not match any archive log in the recovery catalog
结果和我们想的一样,在 rman catalog 中没有任何记录。因此该方法应该是首选。
总结
对已大数据量的迁移工作,使用表空间传输的方法实现是效率比较高的一种方法。
exp/expdp 迁移 metadata , rman convert 迁移数据文件。
他们的联合使用,可以支持跨平台、跨文件系统的迁移,这点在环境复杂的项目中非常有用。