经济普查全国数据库备份方案的选择研究
在经济普查数据处理过程中,为了各专业调查组能顺利地对本专业的数据进行审核汇总等操作,确保数据处理系统数据库的安全,可靠,并在意外发生时能尽快恢复到最近可用的状态,必须做好经常性数据备份。同时,为了充分利用现有的设备能力,我们需要定时进行不同服务器之间数据迁移,然后执行不同的任务,这也要通过导出 /导入的办法实现。
国家和省级经济普查机构数据处理采用的数据库平台是运行在 HP-UX操作系统上的Oracle9i数据库,因此,数据库的备份方案围绕0racle数据库展开讨论。
ORACLE数据库有两类备份方法。
第一类为物理备份,该方法实现数据库的完整恢复,但数据库必须运行在归档模式下(业务数据库在非归档模式下运行),且需要大容量的外部存储设备,例如磁带库;
第二类备份方式为逻辑备份,业务数据库采用此种方式,此方法不需要数据库运行在归档模式下,不但备份简单,而且可以不需要外部存储设备。
ORACLE数据库的逻辑备份分为三种模式:表备份、用户备份和完全备份。
这里不准备深入讨论三种逻辑备份的区别,有关知识请参看参考资料 1。
逻辑备份及恢复是通过 ORACLE提供的命令行工具EXP和IMP结合使用实现的。
参考资料 1在第8章有对于EXP和IMP工具的详尽介绍和分析,我这里提到的仅仅是最常用的几个用法。
可以说由 EXP导出的dmp文件的唯一用途就是用IMP进行数据的导入,但这两个命令的运行时间是很不对称的。
备份和恢复是一个整体的过程,如果是防止系统故障时数据丢失的目的,当然是希望恢复的次数越少越好,哪怕所有的备份都派不上用场。这个时候安全是第一位的。
如果是数据迁移的目的,比如从 A用户到B用户,C服务器到D服务器,而且这种迁移的频率还不低,那么时间因素就值得考虑。
根据以往的经验,导入、导出无非是两种情况,一种是内部格式交换,另一种是和外部文本文件交换。
第一种: EXP导出dmp文件,IMP导入。
第二种:自己编写脚本导出文本文件,用 SQLLDR工具导入。
影响导出的因素,第一是数据量,第二是复杂程度。如果要求只导出符合某些条件的数据,一般比无条件导出要费时。
影响导入的因素,第一是数据量,第二是复杂程度。如果导入的数据库有各种约束,导入时必然要增加检查的时间,如果有索引需要更新,也要额外的时间和资源。
先介绍一下我面对的数据库的情况,每个 Oracle账号(用户名)下有一致的模式,分别是53个记录比较多的基本表和若干由基本表计算得出的尺寸较小的汇总表,由于汇总表的数据依赖于基本表,随之而变,所以基本表是备份的重点,
MAIN_TABLE是主表,其他表通过UUID等关键字和MAIN_TABLE及其他另外的表进行关联,带行代码的表有一个由UUID、CATE_ITEM_CODE和CYC_CODE组合而成的主键约束,
其他不带行代码的表有一个由 UUID和CYC_CODE组合而成的主键约束,MAIN_TABLE除了UUID的主键约束外还具有5个索引。
一组典型的基本表记录列表如下 ,其中,表名中带_SUB的是带行代码的二维表。
"MAIN_TABLE" 7171639 行 772 M
"J601" 5167505 行 1.737 GB
"J602" 2003971 行 567.4M
"JB603" 275534 行 20.86M
"JB603_JB603_SUB3" 536592 行 45.57M
"JB606_JB606_SUB1" 5301882 行 342 M
"JE621_JE621_SUB4" 7664234 行 382.1M
"JE622" 52343 行 9.813M
"JG627" 1795368 行 216.8M
总计 7.3 GB
从列表中可以看出,基层表的数据量确实较大,如何快速备份及恢复(导出及导入)是需要认真研究的。
基于应用程序导入性能的要求,数据库运行在非归档模式,而且在一个阶段中(经常超过 10天)不可停止数据库进行维护操作,因此物理备份不能采用。
一、 Exp/imp命令组合
因为在数据整理阶段,基本表需要进行经常的改错工作,所以需要每日备份。为了能够尽快将数据恢复到某一时间点,我们采用每日执行一次特定用户的 53个基本表的完全备份。
exp tom/tom file=tom.dmp log=tom.log parfile=tables.par direct=y indexes=n
从上述命令行可以看出,我们既指定了用户,又指定了表,参数文件 tables.par中列出了所有需要备份的基本表表名。
direct=y参数使Oracle采用直接路径,它能有效地改善导出速度,所用时间从21分缩短到17分。对于7G字节的数据量来说,这样的导出时间已经是令人非常满意的了。
导入,我们尝试过 4种命令参数
方法 A1
因为原始库分别在 2个用户的基本表中。
因此需要分别导入,一次导入一个用户,串行执行。
导入所用时间 :20:39-10:50=9小时49分
方法 A2
人工并行处理,为了利用 4个CPU的能力,修改参数文件将53个基本表划分为4组,用unix的&命令移到后台并行执行。
exp I0809/I0809@118 file=I0809-p1.dmp log=I0809-p1.log parfile=tables-p1.par direct=y indexes=n &
…
exp I0809/I0809@118 file=I0809-p4.dmp log=I0809-p4.log parfile=tables-p4.par direct=y indexes=n &
如果要关闭 telnet客户端,需要把上述命令保存到批处理文件a.bat ,用 nohup sh a.bat &执行。
imp I0809/I0809 file=I08091202-p1.dmp parfile=tables-p1.par ignore=y log=impI08091202-p1.log &
…
imp I0809/I0809 file=I08091202-p4.dmp parfile=tables-p4.par ignore=y log=impI08091202-p4.log &
如果要关闭 telnet客户端,需要把上述命令保存到批处理文件b.bat ,用 nohup sh b.bat &执行
导入所用时间 =次日10:09-16:50=17小时19分。
方法 A3
根据传统的经验,如果导入数据不及时提交将会占用较大的回滚段,降低速度,所以应该用 commit=y参数。可是,对于这个数据库,即使把buffer设为4096000的大值,commit=y参数也大大增加了所用时间。这里I0809用户已经建好了模式,分别是53个基本表和若干计算表,并且基本表的主键约束和索引也已创建。
imp userid=I0809/I0809 file=I080908111900.dmp parfile=tables.par log=I0809.log ignore=y commit=y buffer=4096000
所用时间 =第3日01:08-20:22=28小时46分。
方法 A4
为了进行比较,新建了一个用户 BEE,不包含任何表。
imp userid=BEE/BEE file=I080908111900.dmp parfile=tables.par log=I0809.log ignore=y
导入所用时间 =13:34 -09:58=3小时36分。
创建索引的语句我们通过下面方法得到。
首先执行表结构及约束、索引的导出,但不导出数据记录。
exp userid=I0809/I0809 file=I0809st.dmp parfile=tables.par rows=n direct=y log=expI0809st.log
然后
imp userid=BEE/BEE file=I0809st08112003.dmp parfile=tables.par log=impI0809st.log indexfile=I0809stindex.sql
我们在 I0809stindex.sql可以看到I0809st08112003.dmp中包含的表结构及约束、索引。
例如:
REM CREATE TABLE "JB603" ("UUID" VARCHAR2(32) NOT NULL ENABLE,
REM "CYC_CODE" VARCHAR2(2) NOT NULL ENABLE, "B03_01" NUMBER(9, 0),
REM "B03_02" NUMBER(9, 0), "B03_03" NUMBER(9, 0), "B03_04" VARCHAR2(1),
REM "B03_INFO1" VARCHAR2(10), "B03_INFO2" VARCHAR2(10), "B03_INFO3"
REM VARCHAR2(10), "B03_INFO4" NUMBER(1, 0), "B03_INFO5" NUMBER(2, 0),
REM "B03_INFO6" NUMBER(2, 0)) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS
REM 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1) TABLESPACE
REM "EPRAS" LOGGING NOCOMPRESS ;
CREATE UNIQUE INDEX "PKJB603" ON "JB603" ("UUID" , "CYC_CODE" )
PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1
FREELIST GROUPS 1) TABLESPACE "EPRAS" LOGGING ;
然后我们可以删除一些 "REM"(表示注释行),整理出一个创建约束、索引的脚本makeindex.sql
CREATE UNIQUE INDEX "PKJB603" ON "JB603" ("UUID" , "CYC_CODE" )
PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1
FREELIST GROUPS 1) TABLESPACE "EPRAS" LOGGING ;
ALTER TABLE "JB603" ADD CONSTRAINT "PKJB603" PRIMARY KEY
("UUID", "CYC_CODE") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255
STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1) TABLESPACE
"EPRAS" LOGGING ENABLE ;
而创建表语句,如 CREATE TABLE "JB603"是不必要的,因为导入dmp时会自动创建,如果写了,oracle将抛出一个错误信息,但不影响其余语句的执行,因此保留也无妨。
@makeindex.sql
重建所有基本表索引总共用时 =02:28:06-02:21:24=6分42。
方法 A5
exp导出不包含约束和索引的数据
exp bee/bee file=beec.dmp log=bee.log parfile=tables.par direct=y indexes=n CONSTRAINTS=n
导出所用时间 =19:17-19:02=17分
在一个用应用程序产生的用户下删除 tables.par中包含的53张表
imp userid=bee4/bee4 file=beec.dmp parfile=tables.par log=beecimp.log ignore=y
date
导入所用时间 =14:53-13:15=1小时38分
@makeindex.sql
date
重建所有基本表索引和约束总共用时 =11:05:51-10:28:26=37:25(索引建好以后,改为主键约束基本不用时间)
这样,我们通过采用 Direct=y参数加快了导出,通过在导出时不导出约束和索引,并删除目标表导入,然后重建索引的办法加快了导入。
在 Oracle 10g中新增加了expdp和impdp命令,这二个命令用到了新的数据泵(Pump)技术,支持并行操作,特别是导入速度有极大的提高。
方法 B1
expdp bee/bee dumpfile=bee-%U.dmp directory=dmpdir logfile=bee..log parallel=5 parfile=tables.par EXCLUDE=INDEX,CONSTRAINT,TABLE_STATISTICS
06:49:40 - 06:32:33 =17分07 虽然expdp不再有direct=y参数,但它默认自动采用直接路径,当无法采用直接路径时改用常规路径。尽管有一些时间用于分析,仍然与exp的速度相当。
impdp bee2/bee2 dumpfile=bee-%U.dmp directory=dmpdir logfile=beei.log parallel=5 parfile=tables.par TABLE_EXISTS_ACTION=REPLACE REMAP_SCHEMA=bee:bee2
导入所用时间 =07:05:11 - 06:49:40=15分31与exp的速度相当,和imp的速度不是一个数量级的,当然这里没有导入约束和索引,但即使导入约束,仍然比imp快了许多,参看下面方法B2。
导入后建立约束和索引的时间, 08:55:42-08:24:38 =31分04
总时间 =17:07+15:31+31:04=63分38
方法 B2
导出时包含索引和约束,但目标表不存在
expdp bee/bee dumpfile=beei-%U.dmp directory=dmpdir logfile=bee.log parallel=5 parfile=tables.par
17:04-16:48-09:36=0:16
impdp bee3/bee3 dumpfile=beei-%U.dmp directory=dmpdir logfile=beeimp.log parallel=5 parfile=tables.par TABLE_EXISTS_ACTION=REPLACE REMAP_SCHEMA=bee:bee3
导入所用时间 =17:57:13-17:04:36=52分37
总时间 =16+52:37=69分
方法 B1和B2两者速度持平,但方法B2步骤简单了许多,更适合一般用户使用。
Exp/imp命令组合小结:
有条件的话,首选 Oracle 10g平台,采用expdp导出包含约束和索引的数据,然后impdp命令导入,一气呵成。虽然只能将dmp文件存在服务器端,但考虑到即使用exp也是telnet到服务器后执行的(为了充分利用服务器的高速I/O和大容量存储,并减少网络流量),两者没有本质的区别。而且expdp/impdp还具有很多可管理的特性,可以在导出/导入过程中挂起、恢复、终止任务。
另一处要注意的是 dmpdir目录需要预先建立,
conn / as sysdba
create directory dmpdir as '/oradata/dmp';
grant read,write ON DIRECTORY dmpdir to tom;
而且给导出和导入用户都授权读写,可以用一个脚本完成,不费事。
GRANT READ ON DIRECTORY "SYS"."DMPDIR" TO "BEE3";
GRANT WRITE ON DIRECTORY "SYS"."DMPDIR" TO "BEE3";
GRANT "CONNECT" TO "BEE3";
GRANT "DBA" TO "BEE3";
GRANT "RESOURCE" TO "BEE3";
如果要在经济普查数据库这样的 Oracle 9i平台导出和导入,采用exp导出不包含约束和索引的数据,再删除目标用户基本表的约束和索引(如果存在),然后imp命令导入,再用脚本建立约束和索引,commit=y参数不必使用。
上述各方法的参数以及运行时间的比较见附表:
(方法A:Oracle9i exp+imp,方法B:10g expdp+impdp)
方法
|
编号
|
提交
|
并行
|
导出约束
|
导出索引
|
导入前删目标表索引和约束
|
导出时间
|
导入时间
<td style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ffffff; WIDTH: 22.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent; mso-border-left-alt: solid windowtext .5pt" val |
---|