正在看的ORACLE教程是:PL/SQL實現Oracle資料庫任務調度。摘要:本文主要就資料庫恢複與系統任務的調度,在結合一般性的資料庫幕後處理的經驗上,提出較為實用而新穎的解決方案,拓寬了資料庫後台開發的思路。
關鍵詞:資料恢複,任務調度,ORACLE,PL/SQL
在資料庫操作中時常會有這樣的情況發生,由於一時的疏忽而誤刪或誤改了一些重要的資料,另外還有一些重要的任務需要周期性地運行。顯然,前一類問題主要是資料備份與恢複方面的,而後一類則主要是系統的任務調度。本文將針對這兩類問題,從應用程式開發角度給出一個解決方案。
一.技術基礎
由於本文是使用PL/SQL作為開發平台來提供解決方案,所以首先瞭解相關的背景知識。
PL/SQL本身只是作為SQL語句的一個補充,通過引入過程化的概念來增強資料庫處理能力。然而,相對於C,C++,JAVA等過程化語言來說,PL/SQL的處理功能依然不夠強大。為此,Oracle資料庫提供了大量的應用程式開發包,來增強應用程式開發能力。根據本文的主題,介紹如下兩個開發包:DBMS_FLASHBACK和DBMS_JOB。
1. DBMS_FLASHBACK包主要是用來進行倒敘查詢使用的,即通過設定查詢時間來確定該時刻下的查詢結果。一般情況下,我們平時使用的查詢是查詢目前時間(sysdate)下的資料。使用DBMS_FLASHBACK包就可以查詢以前資料的狀態,這一功能對於誤處理的情形而言就顯得極為重要。下面是該包中的兩個主要函數介紹:
·Enable與disable:分別是啟動和關閉倒敘查詢功能。應該注意的是,每次啟動倒敘查詢之前應首先關閉倒敘模式。
·Enable_at_time:設定查詢的時間點,它是以目前時間為起點進行設定的。
2. DBMS_JOB包是用來對PL/SQL塊進行調度的實用包,它允許PL/SQL塊在指定的時間內自動運行,類似於VC中的Settimer這樣的定時器。為便於該包的運行,需要首先設定兩個init.ora參數:
·JOB_QUEUE_PROCESS指定啟動的幕後處理數。如果它是0或沒有被設定,將沒有幕後處理進入作業,它們也就不會運行。
·JOB_QUEUE_INTERVAL以秒為單位,指定每一個過程在檢查新的作業前等待的時間。在JOB_QUEUE_INTERVA所指定的時間內,一個作業最多隻能運行一次。
設定好這兩個參數後,就可對程式進行調度了,該包主要使用SUBMIT函數進行調度,該函數的原型為:
submit(返回的作業號,程式過程名,sysdate,下次啟動並執行時間);
二.資料恢複
資料恢複是資料庫本身一個極其重要的功能,通常重要的資料可以通過其系統的資料備份功能來實現,所以在實際的開發中,重要的資料往往容易恢複,反而是一些平常的資料因為誤操作而引起一些麻煩。
對於有經驗的開發人員來說,往往會對那些開發需要的基表(基表就是提供資料來源的資料表)做一些備份。這樣,即使以後出現一些資料誤操作也不會導致重大的事故。
更為實用而又很少為開發人員所使用的方法就是採用倒敘查詢,鑒於前面已經有了一定的技術鋪墊,現在就可以使用DBMS_FLASHBACK包來對資料進行恢複了。為方便講述,假定一個基表emp_table,其表記錄如下:
即此表僅有3條記錄,那麼由於對資料庫的誤操作,導致第一條記錄被刪除,那麼執行下面的SQL語句:
其執行結果為:
由於已經執行了提交操作(COMMIT),所以無法進行復原(ROLLBACK),這樣原來的資料就無法用正常方法進行恢複。不過,由於誤操作的時候在不久以前(假設是5分鐘之前),在這種情況下,可以使用DBMS_FLASHBACK包來恢複資料,可以在SQL*PLUS裡鍵入如下代碼:
execute dbms_flashback.enable_at_time(sysdate-5/1440);
此時,將資料庫調整到5分鐘之前的狀態,如果再執行查詢表的命令就會為如下結果:
那麼就可以在此時將其資料備份到emp_table_bk,即:
這樣,就把以前誤操作的資料給恢複回來了。
從上面的結果看的出,調用DBMS_FLASHBACK包的ENABLE_AT_TIME函數,可以將資料庫的當前查詢時間調整到以前,這樣給資料恢複提供了協助。
在使用DBMS_FLASHBACK包的時候還應該注意以下幾點:
·倒敘查詢是有前提的,即該資料庫必須具有撤消管理功能。具體做法是,DBA應該建立一個撤消資料表空間,並啟動自動撤消管理,並建立一個撤消保留時間窗。這樣,Oracle將在撤消資料表空間中維護足夠的撤消資訊以便在保留時間內支援倒敘查詢。
·由於撤消資料表空間的大小直接決定了倒敘查詢執行的成敗。即撤消資料表空間越大,那麼可以查詢的時間可以越早,那麼對於一般的撤消資料表空間的大小,為了保證倒敘查詢的成功,盡量查詢5天以內的資料,這樣成功的可能性更高一些。
三.任務調度
在UNIX系統中,任務與進程的概念是等同的,即當系統執行一段程式碼時會自動給其分配一個進程號和任務號,這樣使用進程號和任務號就可以對該任務進行操作(如掛起,停止,啟動等)。而Oracle資料庫內部也存在任務調度,比如,需要對某一操作進行周期性的執行,或者是在某事件發生的時候才執行。一般性的做法是使用觸發器,即將所有操作封裝在觸發器裡,然後通過指定觸發事件即可將該操作等待執行。另外,還可以直接利用作業系統來實現,比如在Windows平台就可以編寫Windows指令碼並結合"任務計劃"來實施;如果在Unix平台,就可以寫Shell來實現任務的周期性的執行操作。
而這裡主要是採用ORACLE資料庫的DBMS_JOB包來實現的。
例如,由於每個月都需要對員工進行考評以進行薪水的調整,那麼就需要對emp_table表進行更新處理。更新處理代碼如下:
為了定期每個月都運行上面的程式,可以執行如下代碼:
submit執行後將使得salary_upt過程馬上執行。在上面的代碼中,v_jobNum是該作業返回的作業號(任務號),後面兩個時間分別為開始時間和結束時間,所以salary_upt過程將每隔30天執行一次salary_upt程式,以此達到了定期更新的目的。
如果要禁止該作業的繼續執行,可以執行下面的命令:
使用DBMS_JOB包來實現任務的調度便於跟應用程式整合,有時候這樣處理更為的便捷。
四.小結
很多時候,資料庫的功能可以通過應用程式來進行擴充,對於進行後台資料庫開發操作的使用者而言,除了對資料庫整體架構熟悉以外,掌握一定的應用程式開發能力是很有必要的。系統通過本文能夠給讀者一定的啟發。
本文的開發環境為:
伺服器端:UNIX+ORACLE9.2
用戶端:WINDOWS2000 PRO+TOAD(或者SQL*PLUS)
本文中的代碼在上述環境已調試通過。