数据迁移
何时做迁移?
不同ORACLE版本之间(即大跨度的平台升级时)
不同架构的转换时(如从其他平台转换到ORACLE)
以及其他一些业务需求
数据迁移的工具
A.SQL*LOADER,最古老的数据迁移工具,在不同架构的数据库之迁移变得容易实现,将文本文件轻易的导入到ORACLE数据库中,而不太会出现这样那样的问题,但其速度慢一直是个老大难问题,。它直接连接到ORACLE系统中的表,相当于是ORACLE导入导出的一个客户端工具。在9i之前也使用expd以及impd来进行导入导出,它也是一个ORACLE的导入导出客户端工具,除了受导入对象的限制(文本),速度慢也是其最大缺点。
B.EXPDP/IMPDP,数据泵,听到泵的概念就能想像其功能的强大了,它并不是对数据库中的表直接操作,而是通过一个存储过程(DBMS_DATAPUMP)连接到数据库,相对于用户的客户端而言,使用PL/SQL编写的过程速度远远领先,PL/SQL可以直接访问SGA区,也是其快速度的一个原因,所以数据库泵技术最大的好处就是比以上提示的两种技术要快
C.OMW (ORACLE Migration Workbench ) 比如可以使用SQL SERVER通过JAVA JDBC连接到ORACLE,直接进行导入导出,而可以不再使用SQL*LOADER进行中转,省去了很多麻烦的事,但同时也是一笔不小的开支。
D.ETL (extract transform Loader) 专门用于异构平台的数据迁移的工具,更加适用于数据仓库,在这里仅作一个了解。
在进行数据库的导入导出之前,我们先来看一下一个概念,目录对象,它在本质上和我们要说的导入导出的操作没有什么太大关系。
通过目录对象,来授权ORACLE 数据库用户来访问OS系统中的目录,只有具备了OS系统中对目录的读取权限,SQL*LOADER以及DATA PUMP才能读取客户端的文件。
SQL*LOADER的使用:
EM--->Maintenance--->Data MoveMent--->Move Row Data--->Load Data From User Files
指定它的控制文件(控制文件的写法有些复杂,这里也不再展开)
根据以上的这样一个向导来完成数据的加载
数据的加载方法:
Conventional Load(常规加载): 比如说常规的INSERT 语句来进行加载,使用事务提交COMMIT来进行确认,这样子的话,会不断的redo log产生,还会考虑所有的约束条件等,
同时允许用户在此时修改表。在这种模式下,如果一个很大的库,需要几天几夜才可能完成。
Direct Path Load(直接路径加载):绕过了redo,直接进行数据保存,速度快,其只考虑primary key、unique、not null这三类约束,在整个数据加载过程中,不允许其他用户更改表。同时我们能够看出他的缺陷,一旦出现加载问题,无法进行数据得做,因为它没有激活redo机制。。。所以其风险也是非常大的。
Data Pump的使用:
首先,它是一个存储过程,可以将用户自定用以实现其他功能的PL/SQL加入到存储过程中,进行精确的数据加工,可以明确各种各样的规则限制,可以在分布式的环境中使用网络模式来操作,可以对数据取样,也可以对元数据(描述数据的数据)进行压缩。
数据泵的原理:
在数据库A和数据库B之间建议连接(DB LINK)在一个数据库A的一端使用EXPDP导出,另外一端即可以进行IMPDP导入,相比较SQL*LOADER从A库中导出,转存成文件,再将文件导入到B库中,几乎省去了一半的时间。DBLINK是ORACLE中非常有用的一个工具,可以在使数据从一个库转移到另外一个库,但在OCP的教材中几乎没有涉及,需要多花点时间去整理学习。
如何使用DATA PUMP
我们也提到,它是通过调用DBMS_DATAPUMP这个过程来实现其功能,可以使用:
基于命令行:
EXPDP/IMPDP
基于EM的WEB平台
数据的加载方法,数据泵会自动确定其加载方法,但我们仍然要知道它可以使用以下两种加载方式
直接路径加载:出现在你的数据库表结构如果允许使用直接路径加载,并且希望达到最大的单个流性能时。
外部表加载:这些表没有放在表空间中,也没有放在数据文件中,存于ORACLE外部文件中,使用ORACLE本身的体积变小,当使用的信息文件如是图片,视频等,建议使用外部表。在具有完整性约束条件,列进行了加密,此时会自动选择外部表方式加载。
数据泵加载的好处是可以在作业停止后重新运行(只要元信息没有被破坏),并且不管是之前是遇到故障停止,还是自动停止,都不受影响,不会丢失数据。对于使用data pump时,还有一点需要知道的,只有在ORACLE 10g Enterprise Edition版本中才可以设置并行度的参数。
Data Pump导出、导入的演示:
导出:
创建导出目录
[oracle@ocp10g ~]$ mkdir /tmp/data_pump
SQL> CONN system/oracle;
Connected.
SQL> CREATE DIRECTORY data_pump AS ’/tmp/data_pump’;
Directory created.
创建演示表:
SQL> CONN system/oracle
Connected.
SQL> CREATE TABLE data_pump_tab
2 AS
3 SELECT *
4 FROM dba_users;
Table created.
Table created.
SQL> SELECT *
2 FROM data_pump;
我们在这里使用EM来进行导出:
EM--->SYSTEM用户登录---->Maintenance --->Data Movement---->Export To Export Files
----->在Export Type中选择 Tables框 (输入OS用户的认证信息,比如oracle/password)
----->点Continue--->在Export : Add Tables--->单击Add,指定Schema为SYSTEM, Table选择data_dump(即刚才创建的演示表)--->SELECT按钮---->Next按钮--->选择默认的存放目录(上面创建的DATA_PUMP_TEST)--->Finish按钮
----->Export: Review 这个位置能够看到生成的作业执行脚本--->Submit Job
---->出现Job Activity页面,下面有Search选项,选择Job status为ALL,点Go按钮.
可以看到作业的执行情况。
然后下面就是验证,进入到刚才创建的目录,即/tmp/data_pump目录中,此时里面应该可以看到导出的转储文件和日志文件,可以从*.log这个文件中看到作业的执行情况。
然后我们示例使用SQLPLUS平台进行导入:
在这里需要注意的,我们在指定dump file以及directory时不需要指定路径,否则会出错。
为了方便验证导入的正确性,首先将刚才创建的表删除。
SQL> CONN sysman/oracle;
SQL> DROP TABLE data_pump PURGE;
Table dropped.
[oracle@ocp10g ~]$ impdp userid=system/oracle dumpfile=EXPDAT01.DMP directory=data_pump
Import: Release 10.2.0.1.0 - Production on Sunday, 21 March, 2010 21:08:25
Copyright (c) 2003, 2005, Oracle. All rights reserved.
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
Master table "SYSTEM"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_IMPORT_FULL_01": userid=system/******** dumpfile=EXPDAT01.DMP
directory=data_pump
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "SYSTEM"."DATA_PUMP_TAB" 11.23 KB 28 rows
Job "SYSTEM"."SYS_IMPORT_FULL_01" successfully completed at 21:08:30
导入完成后,以system进入到ORACLE服务器去验证
SQL> SELECT *
2 FROM data_pump_tab;
结果(略),我们可以看到,被我删除的表,又回来了, 这就是data pump的用法。
下面再来说一下SQL*LOADER的用法
同样在这里要注意的是,它一样要求对目录有权限。
使用源文件所在的位置创建目录:
如需要将要/tmp/loader_dir/loader.data文件中的数据导入到SCOTT下面的loader_tab表中,以下是完成这个要求的控制文件和操作细则:
先来准备环境
A.创建文件存储目录
[oracle@ocp10g ~]$ mkdir /tmp/loader_dir
B.准备loader.data文件
[oracle@ocp10g loader_test]$ vim loader.data
1001,bruce
1002,merica
1003,jack
1004,matthew
C.下面我们再以SCOTT来创建一个用来测试的空表,方便我们进行导入,如下所示:
SQL> CREATE TABLE loader_tab (id NUMBER(5),name VARCHAR2(10));
Table created.
D. 设置ORACLE对象目录,首先要为SCOTT用户开启了建立目录的权限,使用以下命令实现:
SQL>CONN /as sysdba; ------>首先连接到sys
Connected.
SQL>GRANT CREATE ANY DIRECTORY TO scott; ---->授予权限
Grant succeeded.
SQL> CONN scott/tiger; ----->切换到scott用户,来建立目录对象
Connected.
SQL> CREATE DIRECTORY loader_dir AS ’/tmp/loader_dir’;
Directory created.
在创建目录对象时要注意的是,系统不会检测指定位置是否存在文件夹,所以一定要当心,为了不要忘记创建,可以像这样事先建立好一个文件夹待使用。
以上是我们的准备工作,那么对于这个简单的例子,我们最重要的就是写一个控制文件了,它用来来描述如何导入指定的文本文件。
比如控制文件描述如下:
[oracle@ocp10g loader_test]$ vim loader.ctl
load data ----->指明操作,是用来加载数据
infile ’loader.data’ "str ’\n’ " ------>来源文件, 并且以换行符作为行分隔
append into table loader_tab ------>加载模式是追加,不会覆盖原有数据
fields terminated by ’,’ ----->列分隔符,以 " ," 分隔。
(id, name) ----->指定插入的列。
~
好了,这个时候,可以执行下面的语句进行测试了:
[oracle@ocp10g loader_dir]$ sqlldr userid=scott/tiger control=/tmp/loader_dir/loader.ctl
SQL*Loader: Release 10.2.0.1.0 - Production on Sun Mar 21 22:35:57 2010
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Commit point reached - logical record count 4
可以看到系统正确导入了4行数据,可以进入到系统中进行验证:
SQL> CONN scott/tiger;
Connected.
SQL> SELECT *
2 FROM loader_tab;
ID NAME
---------- --------------------
100 bruce
101 merica
102 jack
104 matthew
同时,在源文件所在目录下,会生成一个日志文件,也可以从中看出来导入的细节情况:
[oracle@ocp10g loader_dir]$ vim loader.log
1
2 SQL*Loader: Release 10.2.0.1.0 - Production on Sun Mar 21 22:47:35 2010
3
4 Copyright (c) 1982, 2005, Oracle. All rights reserved.
5
6 Control File: /tmp/loader_dir/loader.ctl
7 Data File: /tmp/loader_dir/loader.data
8 File processing option string: "str ’
9 ’ "
10 Bad File: /tmp/loader_dir/loader.bad
11 Discard File: none specified
12
13 (Allow all discards)
14
15 Number to load: ALL
16 Number to skip: 0
17 Errors allowed: 50
18 Bind array: 64 rows, maximum of 256000 bytes
19 Continuation: none specified
20 Path used: Conventional
21
22 Table LOADER_TAB, loaded from every logical record.
23 Insert option in effect for this table: APPEND
24
25 Column Name Position Len Term Encl Datatype
26 ------------------------------ ---------- ----- ---- ---- ------------------ ---
27 ID FIRST * , CHARACTER
28 NAME NEXT * , CHARACTER
29
30
31 Table LOADER_TAB:
32 4 Rows successfully loaded.
33 0 Rows not loaded due to data errors.
34 0 Rows not loaded because all WHEN clauses were failed.
35 0 Rows not loaded because all fields were null.
36
37
38 Space allocated for bind array: 33024 bytes(64 rows)
39 Read buffer bytes: 1048576
40
41 Total logical records skipped: 0
42 Total logical records read: 4
43 Total logical records rejected: 0
44 Total logical records discarded: 0
45
46 Run began on Sun Mar 21 22:47:35 2010
47 Run ended on Sun Mar 21 22:47:35 2010
48
49 Elapsed time was: 00:00:00.20
50 CPU time was: 00:00:00.05
以上是日志输出的详细信息,当然我们还可以使用其他参数让SQLLOADER的导入,以及产生的输出信息更加灵活一些,同时在此要注意的是控制文件的写法,这里仅是一个简单的例子。
| 上一篇:Oracle学习: to_char转数字小结 |
| 下一篇:闪回操作 |