使用DBMS_SCHEDULER排程作業系統shell指令碼

尛樣兒發表於2013-11-21

    在以往的實施中,如果客戶沒有購買第三方備份軟體,通常就使用系統級別的排程器排程資料庫備份指令碼實現資料庫的自動化備份。Linux、AIX平臺使用crontab,Windows平臺使用管理工具下的計劃任務,但這裡會存在一個問題,現在的資料庫很少執行一臺獨立的伺服器上,要麼執行在HA環境下,要麼是RAC資料庫,如果只是某一臺伺服器上部署備份計劃,當這臺伺服器上的例項被切換或出現故障後,那麼備份就可能被中斷;如果在多臺伺服器都部署上備份計劃,會出現重複備份等情況。

    解決這個問題的最簡單方法就是使用Oracle資料庫自身的排程計劃,從10g之後推薦使用DBMS_SCHEDULER包實施排程,當然也可以使用早期的DBMS_JOBS包完成這個工作。

    下面的例子將演示如何使用DBMS_SCHEDULER包排程儲存在作業系統的shell指令碼,我們在實際的部署中可以將這裡的shell指令碼替換成備份指令碼。


1.資料庫版本:
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

2.建立PROGRAM:
SQL> exec dbms_scheduler.create_program( -
> program_name=>'backup_level0', -
> program_type=>'EXECUTABLE', -
> program_action=>'/home/oracle1/backup_level0.sh', -
> enabled=>true, -
> comments=>'oracle database rman level 0 backup');

PL/SQL procedure successfully completed.

3.建立SCHEDULE:
SQL> exec dbms_scheduler.create_schedule( -
> schedule_name=>'bl0s', -
> repeat_interval=>'FREQ=MINUTELY; INTERVAL=0;', -
> comments=>'oracle database rman level 0 backup schedule 1');

PL/SQL procedure successfully completed.

4.建立JOB:
SQL> exec dbms_scheduler.create_job( -
> job_name=>'backup0', -
> program_name=>'backup_level0', -
> schedule_name=>'bl0s', -
> enabled=>true);

PL/SQL procedure successfully completed.

5.測試JOB:
SQL> exec dbms_scheduler.run_job(job_name=>'backup0');

PL/SQL procedure successfully completed.

6.SHELL指令碼內容:
[oracle1@redhat5 ~]$ more backup_level0.sh 
#!/bin/sh
/bin/echo `date` >> /tmp/rman_level0.log

    注意:shell指令碼的最開始一定要加上#!/bin/sh,在使用命令的時候最好寫上全路徑,如果是備份指令碼還應該定義ORACLE_SID、ORACLE_HOME、ORACLE_BASE環境變數。

7.自動JOB建立成功之後,跟蹤/tmp/rman_level0.log日誌:
[oracle1@redhat5 tmp]$ tail -f rman_level0.log
Tue Nov 19 14:51:04 CST 2013
Tue Nov 19 14:55:01 CST 2013
Tue Nov 19 14:55:22 CST 2013
Tue Nov 19 14:56:22 CST 2013
Tue Nov 19 14:57:22 CST 2013
Tue Nov 19 14:58:22 CST 2013
Tue Nov 19 14:59:22 CST 2013
Tue Nov 19 15:00:22 CST 2013

    Oracle JOB每分鐘執行一次backup_level0.sh指令碼。

    對於HA資料庫來說,只需要在兩臺伺服器上的相同位置放上同樣的shell指令碼,不管資料庫例項在哪臺伺服器上執行,備份指令碼都會被成功排程,備份的內容會被放置在相同位置的共享儲存下。

    對於RAC資料庫而言,我會產生這樣的疑問,RAC的所有資料庫例項是並行工作的,部署在兩臺伺服器相同位置的shell指令碼是由哪臺伺服器例項排程的呢?如何控制JOB在哪個例項執行呢?又如何讓Oracle根據伺服器的負載自動選擇執行例項呢?

    簡單的說,對於使用DBMS_SCHEDULER產生的排程來說,是透過JOB關聯JOB_CLASS,JOB_CLASS關聯Service來控制的,Service有自己的首選例項和備用例項,相關聯的JOB預設會由關聯Service的首選例項排程,當首選例項出現問題,JOB會由備用例項排程。如果JOB沒有跟任何JOB_CLASS關聯,這樣的JOB是和預設的Service關聯,預設的Service具有負載均衡的功能,所以這種情況下的JOB會隨機的被RAC例項排程,預設是根據伺服器資源消耗情況進行分配,且始終會被資源消耗更低的伺服器例項排程。更詳細的原理請參考如下文章:


    如果使用DBMS_JOB包排程作業系統shell指令碼的執行,那麼在DBMS_JOB.SUBMIT中有個INSTNACE引數:
    DBMS_JOB.SUBMIT ( 
    job       OUT BINARY_INTEGER,
    what      IN  VARCHAR2,
    next_date IN  DATE DEFAULT sysdate,
    interval  IN  VARCHAR2 DEFAULT 'null',
    no_parse  IN  BOOLEAN DEFAULT FALSE,
    instance  IN  BINARY_INTEGER DEFAULT any_instance,
    force     IN  BOOLEAN DEFAULT FALSE);

   instance引數的含義是:When a job is submitted, specifies which instance can run the job.
   可以為instance引數指定執行例項的例項號,JOB只會在指定的例項執行,即使出現故障也不會在其他例項執行。instance本身具有預設值,預設可能在任何例項執行,節點出現故障會在另外的節點執行此JOB。對於HA環境下的資料庫該引數是沒有意義的,對於RAC而言,推薦也不設定該引數,這樣的JOB才能在節點出現故障的時候被failover。

--end--


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23135684/viewspace-777177/,如需轉載,請註明出處,否則將追究法律責任。

相關文章