【RAC】rac中如何指定job的執行例項

lhrbest發表於2016-03-30

RACrac中如何指定job的執行例項

 

1.1  BLOG文件結構圖

wpsBD8B.tmp 

 

1.2  前言部分

 

1.2.1  導讀和注意事項

各位技術愛好者,看完本文後,你可以掌握如下的技能,也可以學到一些其它你所不知道的知識,~O(∩_∩)O~:

如何指定job的執行例項(重點)

程式碼獲取rac所有節點的IP地址

 

  Tips:

       ① 若文章程式碼格式有錯亂,推薦使用QQ、搜狗或360瀏覽器,也可以下載pdf格式的文件來檢視,pdf文件下載地址:http://yunpan.cn/cdEQedhCs2kFz (提取碼:ed9b 

       ② 本篇BLOG中命令的輸出部分需要特別關注的地方我都用灰色背景和粉紅色字型來表示,比如下邊的例子中,thread 1的最大歸檔日誌號為33thread 2的最大歸檔日誌號為43是需要特別關注的地方;而命令一般使用黃色背景和紅色字型注;對程式碼或程式碼輸出部分的注釋一般採用藍色字型表示

 

  List of Archived Logs in backup set 11

  Thrd Seq     Low SCN    Low Time            Next SCN   Next Time

  ---- ------- ---------- ------------------- ---------- ---------

  1    32      1621589    2015-05-29 11:09:52 1625242    2015-05-29 11:15:48

  1    33      1625242    2015-05-29 11:15:48 1625293    2015-05-29 11:15:58

  2    42      1613951    2015-05-29 10:41:18 1625245    2015-05-29 11:15:49

  2    43      1625245    2015-05-29 11:15:49 1625253    2015-05-29 11:15:53

 

 

 

 

[ZFXXDB1:root]:/>lsvg -o

T_XDESK_APP1_vg

rootvg

[ZFXXDB1:root]:/>

00:27:22 SQL> alter tablespace idxtbs read write;

 

 

====》2097152*512/1024/1024/1024=1G 

 

 

 

本文如有錯誤或不完善的地方請大家多多指正,ITPUB留言或QQ皆可,您的批評指正是我寫作的最大動力。

 

 

1.2.2  本文簡介

記得之前寫健康檢查指令碼的時候需要統計racIP地址,要用到一個包utl_inaddr.GET_HOST_ADDRESS,這樣的話就得去每個例項去查詢,想了想只能是job來完成了,但當時並不知道如何在rac環境中指定相應的例項去執行job,今天又特意研究了一下這個問題終於解決了,小麥苗迫不及待的分享給大家。

 

 

 

 

1.3  相關知識點掃盲(摘自網路)

oracle自從10g開始有2jobdbms_jobDBMS_SCHEDULER,那麼相應的就分2種情況下的指定例項了,先摘抄一點簡單的job知識吧。DBMS_SCHEDULEROracle 10G中新增的一個包,與老版本的dbms_job包相比,dbms_scheduler有很多新特性

所謂出於job而勝於job,說的就是Oracle10g後的新特性Scheduler啦。在10g環境中,ORACLE建議使用Scheduler替換普通的job,來管理任務的執行。其實,將Scheduler描述成管理job的工具已經太過片面了,10G版本中新增的Scheduler絕不僅僅是建立任務這麼簡單。。。。

ORACLE中管理Scheduler是通過DBMS_SCHEDULER包。。。

DBMS_JOBDBMS_SCHEDULER之間的主要區別如下:

1. DBMS_SCHEDULER可以執行儲存的程式、匿名塊以及OS可執行檔案和指令碼(包括linux系統的shell指令碼),而DBMS_JOB只可以執行儲存的程式或匿名的PL/SQL塊。

2. 考慮到增強的元件重用,排程程式的程式單元作為模式物件儲存。DBMS_JOB只有一種元件,即作業;而排程程式具有元件層次結構。

3. 可以使用DBMS_SCHEDULER更具描述性地定義作業或進度表間隔。DBMS_ SCHEDULER也具有更詳細的作業執行狀態以及故障處理和報告功能。

 

1.4  dbms_job下指定例項執行job

1.4.1  相關知識簡介(摘自網路)

 一個JOB在何級別執行是可以定製的。如果把job定義在db級,job可以執行在任何活動的instance上,並遵循job的排程機制;如果把job定義在instance級別上,job將執行在指定的例項上,如因某種異常導致建立job的例項當機,那job將執行在存活的例項上。

  1、目前我們的rac資料庫是通過查詢語句 select job,instance,what from dba_jobs 可以看到instance=0,這表示該jobdb級,可以執行在任何活動的instance上,由job的排程機制決定在哪個例項上執行。也就是說RAC會根據兩臺伺服器的執行狀態來排程JOB在不同的節點例項中執行,一個JOB可以在A機,下一次有可能在B機執行;
  2、通過在排程中指定instance 引數,可以指定job只在某個特定例項上執行,但是如果該例項的伺服器出現故障時,發現job 在例項A上不再執行,也不會切換到其它例項。如果job建立時沒有指定執行在某個例項上,在job當前執行的例項關掉後,卻可以切到其他活動的例項上。
wpsBD9B.tmp

1.4.1.1  官方文件內容

利用小麥苗提供的工具搜尋官方文件,看到如下的內容:

wpsBD9C.tmp 

1.4.1.2  Working with Oracle Real Application Clusters

DBMS_JOB supports multi-instance execution of jobs. By default jobs can be executed on any instance, but only one single instance will execute the job. In addition, you can force instance binding by binding the job to a particular instance. You implement instance binding by specifying an instance number to the instance affinity parameter. Note, however, that in Oracle Database 10g Release 1 (10.1) instance binding is not recommended. Service affinity is preferred. This concept is implemented in the DBMS_SCHEDULER package.

The following procedures can be used to create, alter or run jobs with instance affinity. Note that not specifying affinity means any instance can run the job.

一、 DBMS_JOB.SUBMIT

To submit a job to the job queue, use the following syntax:

DBMS_JOB.SUBMIT(

   job       OUT    BINARY_INTEGER,

   what      IN     VARCHAR2, NEXT_DATE IN DATE DEFAULTSYSDATE,

   interval  IN     VARCHAR2 DEFAULT 'NULL',

   no_parse  IN     BOOLEAN DEFAULT FALSE,

   instance  IN     BINARY_INTEGER DEFAULT ANY_INSTANCE,

   force     IN     BOOLEAN DEFAULT FALSE);

Use the parameters instance and force to control job and instance affinity. The default value of instance is 0 (zero) to indicate that any instance can execute the job. To run the job on a certain instance, specify the instance value. Oracle displays error ORA-23319 if the instance value is a negative number or NULL.

The force parameter defaults to false. If force is TRUE, any positive integer is acceptable as the job instance. If force is FALSE, the specified instance must be running, or Oracle displays error number ORA-23428.

 

二、 DBMS_JOB.INSTANCE

To assign a particular instance to execute a job, use the following syntax:

   DBMS_JOB.INSTANCE(  JOB IN BINARY_INTEGER,

     instance                IN BINARY_INTEGER,

     force                   IN BOOLEAN DEFAULT FALSE);

The FORCE parameter in this example defaults to FALSE. If the instance value is 0 (zero), job affinity is altered and any available instance can execute the job despite the value of force. If the INSTANCE value is positive and the FORCE parameter is FALSE, job affinity is altered only if the specified instance is running, or Oracle displays error ORA-23428.

If the force parameter is TRUE, any positive integer is acceptable as the job instance and the job affinity is altered. Oracle displays error ORA-23319 if the instance value is negative or NULL.

說的還是比較詳細的。

 

1.4.2  一個測試案例(獲取所有節點的IP地址)

程式碼如下,dbms_network_acl_admin主要是為了解決ORA-24247錯誤,很多年不做開發,寫plsql的能力還是存在的,o(_)o

--- ORA-24247, "network access denied by access control list (ACL)"

begin

  dbms_network_acl_admin.drop_acl(acl => 'UTL_INADDR_LHR.xml');

  commit;

end;

/

begin

  dbms_network_acl_admin.create_acl(acl         => 'UTL_INADDR_LHR.xml',

                                    description => 'UTL_INADDR',

                                    principal   => 'MDSYS',

                                    is_grant    => TRUE,

                                    privilege   => 'resolve');

  commit;

 

  dbms_network_acl_admin.add_privilege(acl       => 'UTL_INADDR_LHR.xml',

                                       principal => 'MDSYS',

                                       is_grant  => TRUE,

                                       privilege => 'connect');

  commit;

  

   dbms_network_acl_admin.assign_acl(acl        => 'UTL_INADDR_LHR.xml',

                                     host       => '*');

  commit;

 

end;

/

 

drop table t_ipaddress_lhr; 

create table t_ipaddress_lhr(INST_ID number, host_name varchar2(255), host_ip  varchar2(255) );

 

create or replace view vh_ipaddress_lhr as 

SELECT a.HOST_ID || ': ' || a.HOST_ADDRESS host_ip1,

       a.HOST_ADDRESS host_ip2,

  a.HOST_ID host_name2

        FROM v$diag_alert_ext a

       WHERE a.COMPONENT_ID = 'rdbms'

         AND upper(a.FILENAME) =

             (SELECT upper(substr(d.VALUE, 1, (length(d.VALUE) - 5)) ||

                           'alert' || substr(d.VALUE, -6, 1) || 'log.xml')

                FROM v$parameter d

               WHERE d.NAME = 'background_dump_dest')

         and a.INDX =

             (SELECT max(b.INDX)

                FROM v$diag_alert_ext b

               WHERE b.COMPONENT_ID = 'rdbms'

                 and upper(b.FILENAME) =

                     (SELECT upper(substr(d.VALUE, 1, (length(d.VALUE) - 5)) ||

                                   'alert' || substr(d.VALUE, -6, 1) ||

                                   'log.xml')

                        FROM v$parameter d

                       WHERE d.NAME = 'background_dump_dest'));  

/

 

create or replace procedure ph_ip_lhr as

 

  V_SQL VARCHAR2(4000);

begin

 

  insert into t_ipaddress_lhr

    (inst_id, host_name)

    SELECT v.INSTANCE_NUMBER, v.HOST_NAME FROM v$instance v;

  commit;

 

  V_SQL := 'update t_ipaddress_lhr t

     set t.host_ip = utl_inaddr.GET_HOST_ADDRESS

   where t.inst_id = userenv(''instance'')';

 

  EXECUTE IMMEDIATE V_SQL;

 

  commit;

 

exception

  when others then

 

    V_SQL := 'update t_ipaddress_lhr t

       set t.host_ip =

           (SELECT v.host_ip2 FROM vh_ipaddress_lhr v)

     where t.inst_id = userenv(''instance'')';

    EXECUTE IMMEDIATE V_SQL;

    commit;

 

end ph_ip_lhr;

/

 

DECLARE

  X NUMBER;

begin

 

  for cur in (select b.JOB

                from dba_jobs b

               where b.WHAT = 'ph_ip_lhr;') loop

 

    sys.dbms_ijob.remove(cur.JOB);

    COMMIT;

  end loop;

 

  for cur in (select b.INST_ID from gv$instance b) loop

 

    SYS.DBMS_JOB.SUBMIT(job       => X,

                        what      => 'ph_ip_lhr;',

                        next_date => SYSDATE+cur.inst_id/8640,

                        INTERVAL  => 'null',

                        no_parse  => FALSE,

                        instance  => cur.inst_id);

    COMMIT;

  end loop;

END;

/

 

 

檢視結果:

SELECT * FROM t_ipaddress_lhr;

wpsBDAD.tmp 

 

1.5  DBMS_SCHEDULER下指定例項執行job

 

1.5.1  相關知識簡介

1.5.1.1  JobClasses

JobClasses相當於建立了一個job組,DBA可以將那些具有相同特性的job,統統放到相同的JobClasses

中,然後通過對JobClass應用ORACLE中的"資源使用計劃"特性,就可以對這些job執行過程中所需要的資源分配情況進行管理。

1、建立JobClasses

使用DBMS_SCHEDULER包的CREATE_JOB_CLASS過程建立JobClasses,該過程支援的引數如下,用plsql developer的命令列檢視

16:45:22 SQL> desc dbms_scheduler.create_job_class;

Parameter               Type           Mode Default?

----------------------- -------------- ---- --------

JOB_CLASS_NAME          VARCHAR2       IN           

RESOURCE_CONSUMER_GROUP VARCHAR2       IN   Y       

SERVICE                 VARCHAR2       IN   Y       

LOGGING_LEVEL           BINARY_INTEGER IN   Y       

LOG_HISTORY             BINARY_INTEGER IN   Y       

COMMENTS                VARCHAR2       IN   Y

 

其中:

v JOB_CLASS_NAME:要建立的JobClass的名稱,注意指定的長度不要超過30個字元,也不要與現有JobClass同名;

v RESOURCE_CONSUMER_GROUP:指定建立的JobClass所在的RCG

提示:啥是ResourceConsumerGroup

你可以將其理解成一個資源分配的方式,處於相同RCG組中的使用者、會話、或者物件共用一組資源,

這組資源中可供分配的資源按照DBA指定的方式分配給RCG。如果設計合理,通過這種方式,可以更有效的利用伺服器的資源。

v SERVICE:指定建立的JobClass所在Service,本選項常見於RAC環境,我們都知道RAC環境由多

例項+資料庫組成,此處所指定的Service實際就是指JobClass會在哪個例項上執行

注意:本引數與RESOURCE_CONSUMER_GROUP引數相互衝突,同一個JobClass只同設定兩個參

數中的一個值。

v  LOGGING_LEVEL:指定日誌記錄的級別,有下列三種級別DBMS_SCHEDULER包中的三個常量

① DBMS_SCHEDULER.LOGGING_OFF:關閉日誌記錄功能;

② DBMS_SCHEDULER.LOGGING_RUNS:對該JobClass下所有任務的執行資訊進行記錄;

③ DBMS_SCHEDULER.LOGGING_FULL:記錄該JobClass下任務的所有相關資訊,不僅有任務執行情況,甚至連任務的建立、修改等也均將記入日誌。

一、 官方文件對service的解釋

wpsBDAE.tmp 

service

This attribute specifies the database service that the jobs in this class have affinity to. In an Oracle RAC environment, this means that the jobs in this class only run on those database instances that are assigned to the specific service.

Note that a service can be mapped to a resource consumer group, so you can also control resources allocated to jobs by specifying a service. See DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING for details. If both the resource_consumer_group and service attributes are specified, and if the service is mapped to a resource consumer group, the resource_consumer_group attribute takes precedence.

If no service is specified, the job class belongs to the default service, which means it has no service affinity and any one of the database instances within the cluster might run the job. If the service that a job class belongs to is dropped, the job class will then belong to the default service.

If the specified service does not exist when creating the job class, then an error occurs.

 

 

 

1.5.1.2  建立service

基於RAC環境中使用的應用程式,有時候希望某個特定的應用程式僅僅執行在RAC的子節點,或者說為某些應用程式分配一個首要節點。對此,Oracle 可以使用services來實現。

這個具體可以參考官方文件:Oracle? Database PL/SQL Packages and Types Reference 11g Release 2 (11.2) E40758-03

 

 

 

 

1.5.2  一個測試案例(獲取所有節點的IP地址)

 

--- ORA-24247, "network access denied by access control list (ACL)"

begin

  dbms_network_acl_admin.drop_acl(acl => 'UTL_INADDR_LHR.xml');

  commit;

end;

/

begin

  dbms_network_acl_admin.create_acl(acl         => 'UTL_INADDR_LHR.xml',

                                    description => 'UTL_INADDR',

                                    principal   => 'MDSYS',

                                    is_grant    => TRUE,

                                    privilege   => 'resolve');

  commit;

 

  dbms_network_acl_admin.add_privilege(acl       => 'UTL_INADDR_LHR.xml',

                                       principal => 'MDSYS',

                                       is_grant  => TRUE,

                                       privilege => 'connect');

  commit;

  

   dbms_network_acl_admin.assign_acl(acl        => 'UTL_INADDR_LHR.xml',

                                     host       => '*');

  commit;

 

end;

/

 

drop table t_ipaddress_lhr; 

create table t_ipaddress_lhr(INST_ID number, host_name varchar2(255), host_ip  varchar2(255) );

 

create or replace view vh_ipaddress_lhr as 

SELECT a.HOST_ID || ': ' || a.HOST_ADDRESS host_ip1,

       a.HOST_ADDRESS host_ip2,

  a.HOST_ID host_name2

        FROM v$diag_alert_ext a

       WHERE a.COMPONENT_ID = 'rdbms'

         AND upper(a.FILENAME) =

             (SELECT upper(substr(d.VALUE, 1, (length(d.VALUE) - 5)) ||

                           'alert' || substr(d.VALUE, -6, 1) || 'log.xml')

                FROM v$parameter d

               WHERE d.NAME = 'background_dump_dest')

         and a.INDX =

             (SELECT max(b.INDX)

                FROM v$diag_alert_ext b

               WHERE b.COMPONENT_ID = 'rdbms'

                 and upper(b.FILENAME) =

                     (SELECT upper(substr(d.VALUE, 1, (length(d.VALUE) - 5)) ||

                                   'alert' || substr(d.VALUE, -6, 1) ||

                                   'log.xml')

                        FROM v$parameter d

                       WHERE d.NAME = 'background_dump_dest'));  

/

 

create or replace procedure ph_ip_lhr as

 

  V_SQL VARCHAR2(4000);

begin

 

  insert into t_ipaddress_lhr

    (inst_id, host_name)

    SELECT v.INSTANCE_NUMBER, v.HOST_NAME FROM v$instance v;

  commit;

 

  V_SQL := 'update t_ipaddress_lhr t

     set t.host_ip = utl_inaddr.GET_HOST_ADDRESS

   where t.inst_id = userenv(''instance'')';

 

  EXECUTE IMMEDIATE V_SQL;

 

  commit;

 

exception

  when others then

 

    V_SQL := 'update t_ipaddress_lhr t

       set t.host_ip =

           (SELECT v.host_ip2 FROM vh_ipaddress_lhr v)

     where t.inst_id = userenv(''instance'')';

    EXECUTE IMMEDIATE V_SQL;

    commit;

 

end ph_ip_lhr;

/

 

begin

 

  for cur in (select v.INST_ID,

                     v.INSTANCE_NAME,

                     'INST_LHR_' || v.inst_id service_name,

                     'LHR_RAC' || v.INST_ID || '_JOB_CLASS' job_class_name,

                     'RAC_LHR_' || V.INST_ID JOB_NAME

                from gv$instance v) loop

    begin

      dbms_service.stop_service(service_name  => cur.service_name,

                                instance_name => cur.instance_name);

      dbms_service.delete_service(service_name => cur.service_name);

    exception

      when others then

        null;

    end;

    begin

      dbms_scheduler.drop_job_class(job_class_name => cur.job_class_name,

                                    force          => true);

    exception

      when others then

        null;

    end;

    begin

      dbms_scheduler.drop_job(job_name => CUR.JOB_NAME, force => TRUE);

    exception

      when others then

        null;

    end;

  end loop;

 

  for cur in (select v.INST_ID,

                     v.INSTANCE_NAME,

                     'INST_LHR_' || v.inst_id service_name,

                     'LHR_RAC' || v.INST_ID || '_JOB_CLASS' job_class_name,

                     'RAC_LHR_' || V.INST_ID JOB_NAME

                from gv$instance v) loop

 

    dbms_service.create_service(service_name => cur.service_name,

                                network_name => cur.service_name);

    dbms_service.start_service(service_name  => cur.service_name,

                               instance_name => cur.instance_name);

 

    dbms_scheduler.create_job_class(job_class_name => cur.job_class_name,

                                    service        => cur.service_name);

 

    DBMS_SCHEDULER.create_job(job_name        => 'RAC_LHR_' || CUR.INST_ID,

                              job_type        => 'STORED_PROCEDURE',

                              job_action      => 'ph_ip_lhr',

                              repeat_interval => NULL, --'FREQ=MINUTELY;INTERVAL=1'

                              job_class       => cur.job_class_name,

                              end_date        => NULL,

                              enabled         => TRUE);

 

  end loop;

end;

/

 

檢視結果:

SELECT * FROM t_ipaddress_lhr;

wpsBDBF.tmp 

 

1.6  總結

簡單點:

① dbms_job下指定例項執行job的方法是執行SYS.DBMS_JOB.SUBMIT包建立job的時候指定instance引數,很簡單

② DBMS_SCHEDULER下指定例項執行job稍微有點複雜,建立service,建立job_class,然後建立job才可以,具體參考案例的程式碼。

 





About Me

...............................................................................................................................

● 本文作者:小麥苗,只專注於資料庫的技術,更注重技術的運用

● 本文在itpub(http://blog.itpub.net/26736162)、部落格園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/viewspace-2072635/

● 本文部落格園地址:http://www.cnblogs.com/lhrbest

● 本文pdf版及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● QQ群:230161599     微信群:私聊

● 聯絡我請加QQ好友(646634621),註明新增緣由

● 於 2016-03-30 09:00~ 2016-03-30 19:00 在魔都完成

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

...............................................................................................................................

拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公眾號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的資料庫技術。

【RAC】rac中如何指定job的執行例項
DBA筆試面試講解
歡迎與我聯絡

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

相關文章