一.前言
以下为大型数据库跨平台迁移的一个实际案例,采用了MV(物化视图),Trigger以及EXP/IMP相结合处理迁移数据的方式,最大程度减少迁移停机时间 。总结文档中可能有写的不妥的地方,请大家指正。
二.环境
软件环境
源数据库: Windows2000+Oracle9.2.0.1
目标数据库:Linux AS3.0 + Oracle9.2.0.7
硬件环境
源数据库: DELL PE6600 8GMem,4*2.8GXeon CPU. CX300 Storage
目标数据库:DELL PE6600 8GMem,4*2.8GXeon CPU. CX300 Storage
数据库信息
系统后台数据库,数据库中包含3个主要用户AA ,BB, CC,
OLTP运行模式。数据库总Table数量558个(其中一部分为备用表,暂时没有数据),还包括View, Trigger, Sequences, Types, Resource Plans等。数据库包含的数据类型有varchar2,number, blob, date ( 嚯嚯,还好没有Long类型,不过有也可以处理的) 。数据库磁盘占用空间总大小为300G 。实际数据量大小接近180G .
迁移要求
将WINNT平台下的Oracle9.2.0.1数据库结构及数据全部迁移到RH Linux AS3.0平台下的Oracle9.2.0.7 。 停机时间不多于6小时。
三.规划及实施阶段
558个Table中有3个巨大的含有blob字段的表,其它Table数据量都一般,可以在允许的停机时间(6小时)内exp/imp完成,三个Table中我们以其中一个最大的Table为例来讲解,其它2个Table效仿即可。
Table名称: AA.streamdata
Exp 大小: 130G .
Exp耗时: 7~10小时
AA.streamdata表太大,不能在停机时间范围内完成,考虑使用MV Log方式.
具体规划及实施步骤如下:
1. exp/imp大表之前,请注意要建立源数据库中的streamdata表的mv log ,建立mv log之后对streamdata的操作(update ,delete,insert)都会被记录在mv log中,由于mv log中记录的是操作,不是数据,所以还需要从mv log 中refresh来将真正变化的数据部分存在MV 中,所以还需要在目标数据库(Linux系统平台)中建立对应streamdata表变化部分的MV . 还有一点需要注意,mv log中的delete 操作不会被refresh到变化部分的MV, 所以需要一个Trigger来记录源数据库中streamdata表的删除记录。 具体步骤如下:
a. 在源Windows PDM正式数据库上建立streamdata的Trigger, 用于纪录删除这个表的纪录时候的Log表 (log表名称为streamdata_del_log), 然后建立Trigger(简单,就不写了,DIY吧)。
b. 在源Windows PDM正式数据库上建立streamdata 表的MV Log (用于存储导入导出期间更新,插入的数据行) . 可以看到mlog$_streamdata 物化视图日志表。
SQL> create materialized view log on aa.streamdata
c. 在目标库(Linux-Base)上建立DB Link 连接到源PDM(WINNT)正式库 .
SQL>create public database link pdm connect to aa identified by aa using ‘pdm_win’ ;
d. 在目标库(Linux-Base)上建立一个新的Table: aa.streamdata_mv, 用于存储源数据中的数据变化(由mv log得来的) 。
CREATE MATERIALIZED VIEW "AA"."STREAMDATA_MV" ON PREBUILT TABLE REFRESH FAST ON DEMAND AS select * from aa.streamdata@pdm ;
2. 准备开始导出(exp)正式库中 aa.streamdata 的数据 , 导出期间数据库处于运行状态,所以可能有部分纪录会有更新, 插入, 删除动作 . 这些动作产生的行都会被记录到mv log 中 . 在最后刷新时纪录到STREAMDATA_MV中,最后作数据同步处理。
Exp脚本例子(子查询导出):
exp "'sys/sys as sysdba'" QUERY="WHERE streamid>=1 and streamid<50000" buffer=8192 tables=aa.streamdata feedback=50 consistent=n compress=n filesize=20G log=pdmstream1 file=(pdmstream1_1,pdmstream1_2)
……… 其它脚本依此类推(以streamid为条件) .
导出的时候注意点:
1. 使用 consistent=n
2. 更改参数 : ALTER SYSTEM SET UNDO_RETENTION = 30000;
3. 如果UNDO不够, 需要加大; LOB类型的使用pctversion作为自己的回滚段 .
4. 尽量在系统不繁忙的时候exp .
5. 按照子查询导出 , 避免需要太大undo空间 .
3. Exp出来的dmp文件可以直接导入到Linux-Base的PDM数据库, 同时PDM正式数据库可以进行下一个EXP. 同步进行可以节省时间.
4. 导入期间注意清除归档文件, 观察UNDO, TEMP等 .
5. 停机时间到 , 首先EXP出 BB用户的数据, 包括数据 . (保证用户AP没有连接到正式DB)
6. 然后开始exp出CC用户下的数据, 包括数据 , 同时开始导入BB用户的数据.
7. 导入CC 用户的数据. 导入同时注意清理归档, UNDO, TEMP变化 .
8. 停机期间 , 导出aa下STREAMDATA以外的其它表, 估计EXP需要时间 2小时,然后导入。
9. 确认其它数据都已经导入完成后, 开始处理STREAMDATE 表的差异部份 .
10. Refresh 源数据库中的mv log , 查看mv log 表, 看看是否资料已经消失, 然后查看目标数据库中的streamdata_mv 视图, 应该有大量差异资料行(注意delete的数据是不会记录在这个视图中的) . 开始处理差异数据部分,从目标数据库的记录差异表streamdata_mv中取出primary key,然后使用SQL在目标数据库的streamdata(目前数据已经导入)中删除这些数据行,然后将目标库中的streamdata_mv中的差异数据insert 到目标库中的streamdata中。
11. 导入导出期间被删除的纪录被记录在Trigger写入的LOG表(log表在源数据库中)中, 从中找出纪录行, 然后在目标数据库中删除这些行 。
四.注意事项
1. 注意exp/imp时候是连sequences,view,procedure等都imp到目标库
了,由于streamdata大表是在线导入导出的,最后实施的mv log数据同步,那么最开始exp出来的sequence 中的last value在源数据库中可能已经发生变化,所以请注意,可能需要recreate sequences, 即需要从源库中导出sequences脚本(其中含有每个sequences的最新last value) 。
2. imp数据的时候,注意disable掉目标库中的trigger等。以免出现数据
问题。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/35489/viewspace-84397/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/35489/viewspace-84397/