Oracle数据库迁移相关技巧介绍

数据库 Oracle 数据库运维
在Oracle数据库迁移过程中,会碰到一些平台和版本的问题。本文将为大家介绍的一些Oracle数据库迁移相关技巧。

本文将讲述的是Oracle数据库迁移的一些技巧,包括Oracle数据库迁移前的准备工作,以及不同类型迁移的处理方法。希望对大家了解Oracle数据库迁移有所帮助。51CTO数据库频道之前也曾为大家介绍过《Oracle跨平台迁移结构而不迁移数据方法详解》。

去年年底做了不少系统的数据迁移,大部分系统由于平台和版本的原因,做的是逻辑迁移,少部分做的是物理迁移,有一些心得体会,与大家分享。

首先说说迁移流程,在迁移之前,写好方案,特别是实施的方案步骤一定要写清楚,然后进行完整的测试。我们在迁移时,有的系统测试了四五次,通过测试来完善方案和流程。

针对物理迁移,也即通过RMAN备份来进行还原并应用归档的方式(这里不讨论通过dd方式进行的冷迁移),虽然注意的是要将数据库设为force logging的方式,在用RMAN做全备之前,一定要执行:

  1. view plaincopy to clipboardprint?  
  2. alter database force logging;   
  3. alter database force logging; 

否则可能会产生坏块。

对于逻辑迁移,在job_processes设置为>0的数值之前,注意job的下次执行时间和job所属用户。比如job的定义在之前已经导入,但是在迁移之时,job已经运行过,那么迁移完成之后,job的下次时间还是原来的时间,这样可能会重复运行。另外,job通过IMP导入后,job所属用户会变成导入用户的名称,显然job原来的用户就不能对JOB进行管理了,可以通过下面的sql进行修改:

  1. view plaincopy to clipboardprint?  
  2. update sys.job$ set lowner=cowner , powner=cowner;   
  3. update sys.job$ set lowner=cowner , powner=cowner; 

在迁移之前,应该禁止对系统进行结构上的修改和发布,比如表结构,索引,存储过程包等。

如果是用exp/imp导入的对象,包括存储过程等,应该检查对象是否与原生产库一致,比如由于dblink的原因,imp之后,存储过程不能创建,导致有部分存储过程丢失,尽管这些存储过程可能没有被使用。

下面是一些加快迁移速度的技巧:

通过dblink,使用append insert的方式,同时利用并行,这种方式比exp/imp更快

对于有LONG类型的列,insert..select的方式显然是不行的,可以通过exp/imp的方式,但是这种方式速度非常慢,其原因在于imp时一行一行地插入表。有另外一种方式,即sqlplus的copy命令,下面是一个示例: view plaincopy to clipboardprint?

  1. spool copy_long_table_1.log     
  2. conn / as sysdba     
  3. set copycommit=2000     
  4. set arraysize 30     
  5. set long 10485760     
  6.     
  7. copy from system/xxxx@source_db append username.table_name using select * from username.table_name;     
  8.     
  9. spool off    
  10. exit   
  11.  
  12. spool copy_long_table_1.log  
  13. conn / as sysdba  
  14. set copycommit=2000  
  15. set arraysize 30  
  16. set long 10485760  
  17.  
  18. copy from system/xxxx@source_db append username.table_name using select * from username.table_name;  
  19.  
  20. spool off 
  21. exit 

不过,sqlpus的copy命令不支持有timestamp和lob列类型的表。如果有timestamp类型的表,可以通过在exp时,加上rowid的条件,将一个表分成多个部分同时操作,对于有lob类型的表,也可以同样处理(因为insert …select方式下,有lob类型列时,也同样是一行一行地插入)。注意在这种方式下,就不能使用direct的方式exp/imp。下面是exp导出时parfile示例:

  1. query="where rowid>=dbms_rowid.rowid_create(1,71224,52,9,0) and rowid<=dbms_rowid.rowid_create(1,71224,55,1038344,10000)"    
  2. file=/dumpdata/n1.dmp     
  3. tables=username.table1     
  4. constraints=n     
  5. grants=no    
  6. indexes=no    
  7. buffer=104857600     
  8. ...     
  9. ...     
  10. query="where rowid>=dbms_rowid.rowid_create(1,71224,423,137,0) and rowid<=dbms_rowid.rowid_create(1,71224,432,59272,10000)"    
  11. file=/dumpdata/n6.dmp     
  12. tables=username.table1     
  13. constraints=n     
  14. grants=no    
  15. indexes=no    
  16. buffer=104857600   
  17.  
  18. query="where rowid>=dbms_rowid.rowid_create(1,71224,52,9,0) and rowid<=dbms_rowid.rowid_create(1,71224,55,1038344,10000)" 
  19. file=/dumpdata/n1.dmp  
  20. tables=username.table1  
  21. constraints=n  
  22. grants=no 
  23. indexes=no 
  24. buffer=104857600  
  25. ...  
  26. ...  
  27. query="where rowid>=dbms_rowid.rowid_create(1,71224,423,137,0) and rowid<=dbms_rowid.rowid_create(1,71224,432,59272,10000)" 
  28. file=/dumpdata/n6.dmp  
  29. tables=username.table1  
  30. constraints=n  
  31. grants=no 
  32. indexes=no 
  33. buffer=104857600 

将表分成几部分同时操作,不仅仅可以利用rowid,也可以利用表上的列,比如说,表上有一个created_date的列,并且保证是递增插入数据,那么这种情况下,也可以使用这个字段将表分成不同的范围同时进行导出和导入。不过使用ROWID通常具有更高的效率。

当然对于有lob列的表,可以按上述方式,拆成多个insert方式同时插入,不需要exp/imp。

对于特别大的分区表,虽然使用并行可以提高速度,但是受限于单个进程(不能跨DB LINK进行并行事务,只能并行查询,也即insert..select只能是SELECT部分才能进行并行)的处理能力,这种方式下速度仍然有限。可以并行将数据插入多个中间表,然后通过exchange partition without validation 的方式,交换分区,这种方式将会大大提高了速度。

有朋友可能会问,为什么不并行直接插入分区表,当然如果是非direct path(append)方式,则是没问题的,但是这种方式插入的性能较低。而direct path的方式,会在表上持有mode=6(互斥)的TM锁,不能多个会话同时插入。(update: 在insert 时使用这样的语句:insert into tablename partition (partname) select * from tablename where ….,更简单更有效率。)

迁移时,将数据分成两部分,一部分是历史表,第二部分是动态变化的表,在迁移之前,先导入历史表,并在历史表上建好索引,这无疑会大大减少迁移时业务系统中断时间。
迁移之前,考虑清理掉垃圾数据。

迁移时,应保证表上没有任何索引,约束(NOT NULL除外)和触发器,数据导入完成后,再建索引。建索引时同样,同时使用多个进程跑脚本。索引创建无成后,应去掉索引的PARALLEL属性。

在创建约束时,应按先创建CHECK约束,主键,***键,再创建外键约束的顺序。约束状态为 ENABLE NOVALIDATE,这将大大减少约束创建时间。而在迁移完成后,再考虑设回为ENABLE VALIDATE。

通过使用dbms_stats.export_schame_stats和dbms_stats.import_schame_stats导入原库上的统计信息,而不用重新收集统计使用。
朋友们可以看到,以上均是针对9i的,实际上在10g甚至11g环境下,也仍然很多借鉴意义。当然这些技巧不仅仅用于完整的数据库迁移,也可以应用到将个别表复制到其他数据库上。

这里没有提到的是利用物化视图或高级复制、触发器之类的技术,因为这些技术,毕竟要修改生产库,对生产库的运行有比较大的影响,因此,只有在停机时间要求特别严格,而在这个时间内又不能完成迁移时才应该考虑。

从迁移的经验来说,只有完善的流程,完整的测试才可以保证成功。这里只是列举了一些小技巧,如果对整个迁移过程有兴趣,可以针对这个话题再进行讨论。

原文链接:http://www.laoxiong.net/some_data_migration_tips.html

【编辑推荐】

  1. 浅谈存取Oracle当中扫描数据的方法
  2. Oracle设置系统参数进行性能优化
  3. Oracle数据库维护中的前瞻性
  4. Oracle与SQL Server之间的数据迁移
  5. 实例讲解Oracle到SQL Server主键迁移
责任编辑:彭凡 来源: laoxiong.net
相关推荐

2010-04-07 09:31:02

Oracle数据库

2011-09-02 10:37:15

Oraclesqlload用法

2010-01-07 17:24:12

VB.NET连接数据库

2010-04-21 14:45:39

Oracle数据库

2010-04-20 12:09:31

Oracle数据库

2015-10-28 17:39:04

ORACLE AIO异步IO

2015-10-28 14:45:35

ORACLE AIO异步IO

2010-04-23 09:32:39

Oracle数据库实例

2010-04-23 12:24:06

Oracle数据库

2009-12-29 11:15:45

ADO数据库

2011-09-02 10:06:51

OracleSqlLoad常用技巧

2010-04-06 11:19:28

Oracle数据库

2017-04-07 15:00:57

Lotus-NotesORACLE数据迁移

2019-10-16 11:40:56

数据库PostgreSQL Oracle

2010-04-15 13:01:25

Oracel数据库

2009-08-24 18:09:13

C#调用Oracle数

2009-08-07 18:07:58

C#数据库开发

2011-05-17 13:43:23

Oracle数据库

2010-04-15 09:27:37

Oracle数据库

2010-04-15 08:57:29

Oracle数据库
点赞
收藏

51CTO技术栈公众号