对操作系统进行备份和还原也许是最常用的实际业务环境升级后因多方面原因存在严重问题这时很可能需要还原到升级前的状态因此数据库建立备份并能进行还原就很有意义本文是一个使用C#(Visual Studio )结合Oracle客户端完成还原点的建立与恢复的完整例子
明确还原目标
在建立还原点时首先要明确还原对象我们所提及的还原并不是简单地对数据库某个时间点整个数据库的备份与还原因为在升级后发生的实际业务数据是不能进行还原的
会引起重要问题的主要是程序在数据库中体现在包函数和存储过程以及与流程相关的参数方案等核心字典数据与界面层的一致性而具体业务中产生的数据如收费项目收费明细等是不能进行还原的明确还原目标后问题的解决就有方向性了
要建立还原点首先要了解数据库中关键对象的存放位置对于包函数等可以在Oracle的数据库视图user_source中找到
备份建立还原对象列表
在建立C#的工程之后今天我们利用配置文件nfigxml设定了相应的导出对象Oracle连接等内容如图
这样参数就可以在CONFIG中进行调整了在进行备份时我们首先要取得相关的程序列表下面的语句可以找到我们需要的导出对象
selectdistinctusnameustypefromuser_sourceuswhereustypein(PROCEDUREFUNCTIONPACKAGEPACKAGEBODY);
可以使用 configurationAppSettings来取得配置文件中的设置如导出对象数据库连接回滚目录如
ls_configs=(string)(configurationAppSettingsGetValue(导出对象typeof(string))); 首先针对导出对象所定义的串进行拆分ls_typeinfo存放需要导出的类型并建立Oracle的数据库连接再根据需要取得数据查询结果
ls_querysql=SelectdistinctUsName
ustypeFromUser_SourceUswhereustypein(+ls_typeinfo+)orderbyusNameusType;
OracleCommandCommandText=ls_querysql;
OracleCommandCommandType=CommandTypeText;
//如何解析commandText的值
OracleDataReadermyReader=OracleCommandExecuteReader(CommandBehaviorCloseConnection);
while(myReaderRead())
//使用OracleDateReader前进到下一条记录 通过循环获得信息列表存放到对象列表listPrcInfo中它包括两个项目分别就是对象名strName对象类别strType
备份有进度地产生各个对象体
生成了对象列表后再根据每个对象名和对象类别来读取内容相对来说就比较简单只要使用以下方法
ls_querysql = Select usline ustext From User_Source Us where usname = + listPrcInfo[i]strName + and ustype=+listPrcInfo[i]strType+ order by usline ; OracleCommandCommandText = ls_querysql; OracleCommandCommandType = CommandTypeText;//如何解析commandText的值 来读取对象的程序内容并按照我们在CONFIG中所对应的各种文件扩展名来保存文件:
)thisstylewidth=; border=>
注意由于我们数据库程序需要使用SQLPLUS来进行导入因此最后一行我们需要写入结束标志符即/符号它的最后内容是这样的
image onmousewheel=javascript:return big(this) height= alt= hspace= src=http://imgeducitycn/img_///png width= onload=javascript:if(thiswidth>)thisstylewidth=; border=>
由于表的导出我们依赖数据库的导出功能只要使用exp命令导出指定的字典表即可即与具体业务无关的核心字典表如功能列表参数列表菜单项目等基本上使用类似于以下的命令结构即可完成
expexe his/his@mytest file=d:\roll\rolldat tables=(%) 其中的%所对应的项目是我们需要导出的表项目由于导入功能的特殊性会在导入功能中着重介绍
还原还原的流程
前文可以看出创建还原点的重点在于如何把所有数据库中的程序进行导出对于关键字典的备份反而比较简单接下来对数据进行还原即关键字典数据处理要加以注意还原的处理流程是
对于当前数据库中的字典数据再次创建备份不过本次备份是在数据库中以表的方式进行备份(因为还原时关键字典表中的数据仍可能会有用到的数据所以需要备份)同时DROP掉相应的字典表
利用Oracle的IMP命令将数据备份的字典数据进入导入(对于表上的触发器其实是表的附加属性在导出时会自动备份导入时也会自动加上)
对于数据库中的程序则利用SQLPLUS执行脚本的方法来完成即建立相应的执行脚本(由于程序都是升级工具升级上来的还原要再升级其程序部分的升级可在升级工具脚本中找到)
还原创建还原脚本
还原脚本分为表的脚本和程序还原脚本表处理部分首先使用
ls_querysql = Select to_char(sysdateyyyymmddhhmiss) from dual ; 取得时间戳表示当前进行还原操作的时间点再利用
ls_tables = (string)(configurationAppSettingsGetValue(导出表 typeof(string))); 取得还原时的表最终生成类似于以下的脚本(tabbaksql)
Create table Rgy_canshu as select * from gy_canshu;
drop table gy_canshu;
Create table Rxt_selectsql as select * from xt_selectsql;
drop table xt_selectsql;
…… 通过 sqlplus his/his@mytest @tabbaksql就可以执行上述脚本对于数据库的程序体也需建立相应脚本考虑到我们建立的还原点数据可能会备份至新目录所以我们利用在建立还原点时的列表文件prclst结合配置中设定的目录重新生成新的执行脚本myprcsql
swImpWriteLine(rem 执行导入所有的存储过程);
swImpWriteLine(ls_sqlplus + + ls_database + @ + ls_path + \\myPrcsql);
//执行导入所有的存储过程
swProcWriteLine( set define off);
swProcWriteLine(spool + ls_path + \\update_logtxt);
while ( (ls_read = srListReadLine() ) != null )
{
swProcWriteLine(prompt +ls_read );
swProcWriteLine(@+ls_path+\\+ls_read);
}
swProcWriteLine(exit); 生成脚本目的就是把还原点的程序重新导入因此生成的结果主要是以下的内容
set define off spool d:\roll\update_logtxt prompt COMPILE_ERRORprc @d:\roll\COMPILE_ERRORprc exit 核心内容生成以后再生成一个运行的批处理即可
…\sqlplusexe his/his@mytest @d:\roll\tabbaksql …\impexe his/his@mytest file=d:\roll\rolldat full=y …\sqlplusexe his/his@mytest @d:\roll\myPrcsql del d:\roll\imptmpfile 并使用Process来完成它的调度
Process pro = new Process(); proStartInfoFileName = ls_path + \\myImpbat;
proStartInfoWindowStyle = ProcessWindowStyleMinimized;
在调度前生成临时文件imptmpfile批处理中完成后删除此文件这样程序只要查看文件是否存在来探知进程是否完成
while(FileExists(ls_tmpfile))
{
ldt_end=DateTimeNow; lb_nameText=(ldt_endldt_start)ToString();
ApplicationDoEvents();
}
一个完整样例我们就做成了通过建立还原点处理数据备份程序备份然后再到还原时备份字典表删除表表导入和数据库程序的导入(如图)
image onmousewheel=javascript:return big(this) height= alt= hspace= src=http://imgeducitycn/img_///png width= onload=javascript:if(thiswidth>)thisstylewidth=; border=>
更进一步
还原工具完成了我们单次的备份与还原实际上还有一些工作可以加强深入
可以利用数据库时间作为还原点标记建立目录方便建立多个还原点
还原时建立相应的日志标记还原时间点便于查看还原状况
如果数据库中的程序如包函数等可以查看最后的时间戳查看是否在建立还原点之后发生变化还原时只要还原时间戳有变化的程序提高还原效率
由于我们是以还原点为概念因此可以忽略升级过程中对数据处理的记录因为要把升级过程的变化记录下来再进行逆操作实际上是非常困难的因此在解决实际问题时有时候找到合适的突破点理解处理问题的核心要素非常重要这样就有助于事半功倍的效果