詳解C#完成Oracle數據庫鏡像與還原
對于C#相關開發技巧,51CTO向您推薦《C#實用基礎教程》和《體驗Visual Studio 2008展望2010》專題來更深入的理解。
開發工具:Visual Studio 2008 C#,Oracle管理工具
對操作系統進行備份和還原也許是最常用的。實際業務環境升級后,因多方面原因存在嚴重問題,這時很可能需要還原到升級前的狀態。因此數據庫建立備份并能進行還原就很有意義。本文是一個使用C#(Visual Studio 2008)結合Oracle客戶端完成還原點的建立與恢復的完整例子。
明確還原目標
在建立還原點時,首先要明確還原對象,我們所提及的還原并不是簡單地對數據庫某個時間點整個數據庫的備份與還原,因為在升級后發生的實際業務數據是不能進行還原的。
會引起重要問題的主要是程序,在數據庫中體現在包、函數和存儲過程以及與流程相關的參數、方案等核心字典數據與界面層的一致性。而具體業務中產生的數據如收費項目、收費明細等,是不能進行還原的,明確還原目標后,問題的解決就有方向性了。
要建立還原點,首先要了解數據庫中關鍵對象的存放位置,對于包、函數等可以在Oracle的數據庫視圖user_source中找到。
備份:建立還原對象列表
在建立C#的工程之后,今天我們利用配置文件app.config.xml,設定了相應的“導出對象”,“Oracle連接”等內容,如圖001:

這樣參數就可以在CONFIG中進行調整了。在進行備份時,我們首先要取得相關的程序列表,下面的語句可以找到我們需要的導出對象:
- selectdistinctus.name,us.typefromuser_sourceuswhereus.typein('PROCEDURE','FUNCTION','PACKAGE','PACKAGEBODY');
可以使用configurationAppSettings來取得配置文件中的設置,如導出對象、數據庫連接、回滾目錄,如:
- ls_configs=(string)(configurationAppSettings.GetValue("導出對象",typeof(string)));
首先針對“導出對象”所定義的串進行拆分,ls_typeinfo存放需要導出的類型,并建立Oracle的數據庫連接,再根據需要取得數據查詢結果:
- ls_querysql="SelectdistinctUs.Name,us.typeFromUser_SourceUswhereus.typein("+ls_typeinfo+")orderbyus.Name,us.Type";
- OracleCommand1.CommandText=ls_querysql;
- OracleCommand1.CommandType=CommandType.Text;//如何解析commandText的值
- OracleDataReadermyReader=OracleCommand1.ExecuteReader(CommandBehavior.CloseConnection);
- while(myReader.Read())//使用OracleDateReader前進到下一條記錄
通過循環,獲得信息列表存放到對象列表listPrcInfo中,它包括兩個項目,分別就是:對象名strName,對象類別strType。
備份:有進度地產生各個對象體
生成了對象列表后,再根據每個對象名和對象類別來讀取內容,相對來說就比較簡單,只要使用以下方法:
- ls_querysql = " Select us.line, us.text From User_Source Us
- where us.name = '" + listPrcInfo[i].strName +"'
- and us.type='"+listPrcInfo[i].strType+"'
- order by us.line ";
- OracleCommand1.CommandText = ls_querysql;
- OracleCommand1.CommandType = CommandType.Text;//如何解析commandText的值
來讀取對象的程序內容,并按照我們在CONFIG中所對應的各種文件擴展名來保存文件:

注意,由于我們數據庫程序需要使用SQLPLUS來進行導入,因此***一行我們需要寫入結束標志符,即“/”符號,它的***內容是這樣的:

由于表的導出我們依賴數據庫的導出功能,只要使用exp命令導出指定的字典表即可。即與具體業務無關的核心字典表,如功能列表、參數列表、菜單項目等,基本上使用類似于以下的命令結構即可完成 :
- exp.exe his3/his3@mytest file=d:\roll\roll.dat tables=(%1)
其中的%1所對應的項目,是我們需要導出的表項目,由于導入功能的特殊性,會在導入功能中著重介紹。
還原:還原的流程
前文可以看出,創建還原點的重點在于如何把所有數據庫中的程序進行導出,對于關鍵字典的備份反而比較簡單。接下來對數據進行還原,即關鍵字典數據處理要加以注意。還原的處理流程是:
1、 對于當前數據庫中的字典數據再次創建備份,不過本次備份是在數據庫中以表的方式進行備份(因為還原時關鍵字典表中的數據仍可能會有用到的數據,所以需要備份),同時DROP掉相應的字典表;
2、 利用Oracle的IMP命令,將數據備份的字典數據進入導入(對于表上的觸發器,其實是表的附加屬性,在導出時會自動備份,導入時也會自動加上)。
3、 對于數據庫中的程序,則利用SQLPLUS執行腳本的方法來完成,即建立相應的執行腳本(由于程序都是升級工具升級上來的,還原要再升級,其程序部分的升級可在升級工具腳本中找到);
還原:創建還原腳本
還原腳本分為表的腳本和程序還原腳本,表處理部分,首先使用:
- ls_querysql = " Select to_char(sysdate,'yyyymmddhh24miss') from dual ";
取得時間戳,表示當前進行還原操作的時間點,再利用:
- ls_tables = (string)(configurationAppSettings.GetValue("導出表", typeof(string)));
取得還原時的表,最終生成類似于以下的腳本(tabbak.sql):
- Create table R20100213110513gy_canshu as select * from gy_canshu;
- drop table gy_canshu;
- Create table R20100213110513xt_selectsql1 as select * from xt_selectsql1;
- drop table xt_selectsql1;
- ……
通過 sqlplus his3/his3@mytest @tabbak.sql就可以執行上述腳本。對于數據庫的程序體,也需建立相應腳本,考慮到我們建立的還原點數據可能會備份至新目錄,所以我們利用在建立還原點時的列表文件prc.lst,結合配置中設定的目錄,重新生成新的執行腳本myprc.sql
- swImp.WriteLine("rem 執行導入所有的存儲過程");
- swImp.WriteLine(ls_sqlplus + " " + ls_database + " @" + ls_path + "\\myPrc.sql"); //執行導入所有的存儲過程
- swProc.WriteLine( "set define off");
- swProc.WriteLine("spool " + ls_path + "\\update_log.txt");
- while ( (ls_read = srList.ReadLine() ) != null ){
- swProc.WriteLine("prompt "+ls_read );
- swProc.WriteLine("@"+ls_path+"\\"+ls_read);
- }
- swProc.WriteLine("exit");
生成腳本目的就是把還原點的程序重新導入,因此生成的結果主要是以下的內容:
- set define off
- spool d:\roll\update_log.txt
- prompt COMPILE_ERROR.prc
- @d:\roll\COMPILE_ERROR.prc
- ......
- exit
核心內容生成以后,再生成一個運行的批處理即可:
- …\sqlplus.exe his3/his3@mytest @d:\roll\tabbak.sql
- …\imp.exe his3/his3@mytest file=d:\roll\roll.dat full=y
- …\sqlplus.exe his3/his3@mytest @d:\roll\myPrc.sql
- del d:\roll\imptmp.file
并使用Process來完成它的調度:
- Process pro = new Process();
- pro.StartInfo.FileName = ls_path + "\\myImp.bat";
- pro.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
在調度前生成臨時文件imptmp.file,批處理中完成后刪除此文件,這樣程序只要查看文件是否存在,來探知進程是否完成。
- while(File.Exists(ls_tmpfile)){
- ldt_end=DateTime.Now;
- lb_name.Text=(ldt_end-ldt_start).ToString();
- Application.DoEvents();
- }
一個完整樣例我們就做成了,通過建立還原點處理數據備份、程序備份,然后再到還原時,備份字典表、刪除表、表導入和數據庫程序的導入(如圖004):

更進一步
還原工具完成了我們單次的備份與還原,實際上還有一些工作可以加強深入:
1、 可以利用數據庫時間作為還原點標記建立目錄,方便建立多個還原點;
2、 還原時,建立相應的日志,標記還原時間點,便于查看還原狀況;
3、 如果數據庫中的程序如包、函數等可以查看***的時間戳,查看是否在建立還原點之后發生變化,還原時只要還原時間戳有變化的程序,提高還原效率。
由于我們是以還原點為概念,因此可以忽略升級過程中對數據處理的記錄。因為要把升級過程的變化記錄下來再進行逆操作,實際上是非常困難的。因此在解決實際問題時,有時候找到合適的突破點,理解處理問題的核心要素非常重要,這樣就有助于事半功倍的效果。
原文標題:C#打造數據庫鏡像與還原:還原無處不在,數據庫也不例外
鏈接:http://www.cnblogs.com/hzspa/archive/2010/05/13/1735007.html
【編輯推薦】


















