Oracle 数据库 10g 中的新的实用程序使其性能和多功能性达到了新的水平。
Oracle 数据库 10g 中增加的叫做 Oracle Data Pump (数据泵)的新的导入和导出特性,彻底改变了数据库用户已经习惯的过去几代 Oracle 数据库的客户 / 服务器工作方式。现在服务器可以运行导出和导入任务。你可以通过并行方式快速装入或卸载大量数据,而且你可以在运行过程中调整并行的程度。导出和导入任务现在可以重新启动,所以发生故障不一定意味着要从头开始。 API 是公诸于众的,并且易于使用;用 PL/SQL 建立一个导入和导出任务非常简单。一旦启动,这些任务就在后台运行,但你可以通过客户端实用程序从任何地方检查任务的状态和进行修改。
体系结构
在 Oracle 数据库 10g 之前(从 Oracle7 到 Oracle9I ),导入和导出实用程序都作为客户端程序运行,并且完成大量工作。导出的数据由数据库实例读出,通过连接传输到导出客户程序,然后写到磁盘上。所有数据在整个导出进程下通过单线程操作。今天的数据量比这个体系结构最初采用的时候要大得多,使得单一导出进程成了一个瓶颈,因为导出任务的性能受限于导出实用程序所能支持的吞吐量。
在 Oracle 数据库 10g 和全新的数据泵( Data Pump )体系结构下,如今所有的工作都由数据库实例来完成。数据库实例可以用两种方法来并行处理这些工作:通过建立多个数据泵工作进程来读 / 写正在被导出 / 导入的数据,以及建立并行 I/O 服务器进程以更快地选取( SELECT )或插入( INSERT )这些数据。这样,单进程瓶颈再也就不存在了。
数据泵任务用新的 DBMS_DATAPUMP PL/SQL API 来建立、监测和调整。新的导入和导出实用程序(分别为 impdp 和 eXPdp )对于这个 API 来说只是命令行接口。你可以使用数据泵导出实用程序初始化一个任务,例如一个导出任务。然后你就可以关闭你的客户端,回家过夜和享用晚餐,而你的任务会一直运行。到了深夜,你可以重新连接到那个任务,检查其状态,甚至可以提高并行程度,以便在深夜系统没有用户在用的情况下多完成一些工作。第二天早上,你可以降低并行度甚至挂起该任务,为白天在线的用户释放资源。
重新启动任务的功能是数据泵体系结构的一个重要特性。你可以随时停止和重启动一个数据泵任务,比如为在线用户释放资源。你还可以从文件系统的空间问题中轻松地恢复。假如一个 12 小时的导出任务在进行了 11 小时后因磁盘空间不够而失败,那么你再也不用从头开始重新启动该任务,重复前面 11 小时的工作。而是你可以连接到这个失败的任务,增加一个或多个新的转储( dump )文件,从失败的地方重新启动,这样只需一个小时你就可以完成任务了。这在你处理很大数据量时非常有用。
对文件系统的访问
由服务器处理所有的文件 I/O 对于远程执行导出和导入任务的数据库治理员来说非常有利。如今,用户可以很轻松地在类似 UNIX 的系统 ( 如 Linux) 上 telnet 或 ssh 到一个服务器,在命令行方式下初始化一个运行在服务器上的导出或导入任务。然而,在其他操作系统上就不那么轻易, Windows 是最明显的例子。在推出数据泵之前,要从一个 Windows 系统下的 Oracle 数据库中导出大量数据,你很可能必须坐在服务器控制台前发出命令。通过 TCP/IP 连接导出数据只对小数据量是可行的。数据泵改变了这一切,因为即使你通过在你的客户端上运行该导出和导入实用程序来初始化一个导出或导入任务,该任务其实也运行在服务器上,所有的 I/O 也都发生在该服务器上。
出于安全性考虑,数据泵要求你通过 Oracle 的目录对象来指定其中存放着你要建立或读取的转储文件的目标目录。例如:
CREATE DirectorY export_dumps
AS 'c:\a';
GRANT read, write
ON DIRECTORY export_dumps
TO gennick;
我以 SYSTEM 身份登录到我的实验室数据库上,并执行以上语句来建立一个目录对象,这个目录对象指向了我磁盘上的一个临时目录,以用来存放导出的转储文件。 GRANT 语句为用户 gennick- 就是我 - 分配了访问该目录的权限。我给自己分配读 / 写权限,因为我将导出和导入数据。你可以为一个用户分配读权限,限制他只能导入数据。
启动一个导出任务
你可以使用新的 expdp 实用程序来启动一个导出任务。因为参数与老的 exp 实用程序不同,所以你得熟悉这些新的参数。
你可以在命令行中指定参数,但在本文中我使用了参数文件。我想导出我的整个模式( schema ),使用了以下参数:
DUMPFILE=gnis%U.dmp
DIRECTORY=export_dumps
LOGFILE=gnis_export.log
JOB_NAME=gnis_export
DUMPFILE 指定我将向其中写入被导出数据的文件。 %U 语法给出了一个增量计数器,得到文件名 gnis01.dmp 、 gnis02.dmp 等。 DIRECTORY 指定了我的目标目录。
我的 LOGFILE 参数指定了日志文件的名字,这个文件是为每个导出任务默认创建的。 JOB_NAME 给任务指定了一个名字。我选择了一个易于记忆(和输入)的名字,因为我可能需要在后面才连接这个任务。要注重在指定任务名称时不要与你登录模式( schema )中的模式对象名称冲突。数据泵在你的登录模式中建立一个被称为任务主表的数据表,该表的名字与任务的名字相匹配。这个数据表跟踪该任务的状态,并最终被写入转储文件中,作为该文件所含内容的一个记录。
清单 1 显示了一个导出任务已被启动。该任务所做的第一件事是估计所需的磁盘空间大小。当估计值显示出来后,我按 ctrl-C 进入一个交互式的导出提示窗口,然后使用 EXIT_CLIENT 命令回到我操作系统的命令窗口。该导出任务仍然运行在服务器上。
注重,假如我要做并行导出并且将我的 I/O 分布在两个磁盘上,那么我可以对 DUMPFILE 参数值做出修改,并如下添加 PARALLEL 参数和值,如下所示:
DUMPFILE=export_dumps01:gnis%U.dmp,
export_dumps02:gnis%U.dmp
PARALLEL=2
注重,在这个并行导出任务中,目录名作为文件名的一部分来被指定。
检查状态
你可以随时连接到一个运行中的任务来检查其状态。要连接到一个导出任务,必须执行一条 expdp 命令,使用 ATTACH 参数来指定任务名称。 清单 2 显示了到 GNIS_EXPORT 任务的连接。当你连接到一个任务, expdp 显示该任务的相关信息和当前状态,并为你提供一个 EXPORT 提示符。
当你连接到了一个任务后,你可以随时执行 STATUS 命令查看当前状态,如 清单 3 所示。你还可以执行 CONTINUE_CLIENT 命令返回到显示任务进度的日志输出状态,该命令可以被缩写成如 清单 4 所示的 CONTINUE 。
你可以通过查询 DBA_DATAPUMP_JOBS 视图快速查看所有数据泵任务的状态。你不能获得 STATUS 命令所给出的具体信息,但你可以快速查看到哪些任务在执行、哪些处于空闲状态等。另一个需要了解的视图是 DBA_DATAPUMP_SESSIONS ,它列出了所有活跃的数据泵工作进程。
从故障中恢复
重启动任务的能力使你可以从某些类型的故障中恢复过来。例如, 清单 5 显示了一个用完了转储文件空间的导出任务的日志文件的结尾部分。然而,什么也没有丢失。该任务只是进入了一个空闲状态,当你连接到该任务并查看状态输出时就可以看到这一点。这个状态不显示任务空闲的原因。要确定这是因为转储文件的空间不够了,则你需要查看日志文件。
连接到因转储文件空间不够用了而停止的任务后,你可以在两个操作中选择其一:你可以使用 KILL_JOB 命令来中止该任务,或者增加一个和多个转储文件来继续该任务的运行。假如空间不够的问题是因为磁盘空间不足,则当然你要确保你增加的文件是在另一个有可用空间的磁盘上。你也许需要创建一个新的 Oracle 目录对象来指向这一新位置。
清单 6 使用 ADD_FILES 命令为我的空闲任务增加两个文件。这两个文件位于不同的目录中,它们都不同于为该任务的第一个转储文件所指定的目录。我使用 START_JOB 命令来重新启动该任务,然后使用 CONTINUE 查看屏幕上滚动的其余日志输出。
导入任务不会受到卸载( dump )文件空间不足的影响。但是,它们可能会受到数据表空间不足或无法扩展表空间的影响。导入的恢复过程和导出任务的基本上相同。首先,通过向表空间增加一个数据文件、扩展一个数据文件或其他方法来提供可用空间。然后连接到该任务,执行 START_JOB 命令。导入任务将从它中断的地方继续执行。
导入选定的数据
本文中的例子到目前为止显示的是对用户 GENNICK 拥有的所有对象进行模式( schema )数据库级别的导出。为了展示数据泵的一些新的功能,我要导入那些数据,而且为了使问题更有意思,我列出了以下要求:
仅导入 GNIS 数据表
将该数据表导入到 MICHIGAN 模式中
仅导入那些与密歇根州相关的数据行
不导入原始的存储参数
一开始,我可以在我的导入参数文件中写出以下四行:
DUMPFILE=gnis%U.dmp
DIRECTORY=export_dumps
LOGFILE=gnis_import.log
JOB_NAME=gnis_import
这四行没有什么新意。他们指定了转储文件、目录、日志文件和该任务的名称。根据我们的四个要求,我可以使用 INCLUDE 参数将导入操作限制在我们感爱好的一个数据表上:
INCLUDE=TABLE:"= 'GNIS'"
INCLUDE 是个很有意思的参数。当你需