您好、欢迎来到现金彩票网!
当前位置:21点 > 子队列 >

数据复制中的定时任务机制

发布时间:2019-07-10 10:17 来源:未知 编辑:admin

  本文首先简单介绍了Oracle 8的数据复制的基本概念,然后详细介绍了实现Oracle 8数据复制延迟事务队列转发的Oralce 8任务队列机制,包括“任务队列”子系统的安装,API编程接口DBMS_JOB包的介绍以及API过程中各参数的概念,任务队列的体系结构和运行环境,任务队列数据字典视图以及时间间隔(interval)参数的算法等。

  复制,顾名思义就是将数据库中的数据拷贝到不同物理地点的数据库中以支持分布式应用,它是整个分布式计算解决方案的一个重要组成部分。Oracle8的数据复制按功能主要分为三类:基本(简单)复制、高级复制和混合复制,而高级复制又可分为多主节点复制和可更新快照复制。图1是一个简单的Oracle数据复制示意图。

  图1是Oracle数据复制的一个简单示意,并不代表任何的复制类型。在节点1如果需要复制的数据库表发生变化(插入、删除或者更新等),则Oracle采用某种内部机制将这种变化放在一个延迟事务队列(DEFTRAN)中。在一个特定的时间或者是某个特定时间间隔后,Oracle将延迟事务队列中的变化“推”到数据库节点2.如果在节点2上要复制的库表发生变化,也采用同样的机制。如果在传播过程中发生错误,则将该错误放在错误队列DEFERROR中。

  Oracle对于存放在延迟事务队列中的事务是如何处理的呢?这就是Oracle的任务队列机制。Oracle的任务队列可以使我们定时或者以一定的时间间隔重复执行Oralce的PL/SQL程序(也就是所说的任务)。任务队列使用最多的地方就是Oracle的数据复制中的定时复制任务,Oracle任务队列子系统最早设计的目的就是为了定时刷新Oracle快照(Oracle简单复制)。当然,现在Oracle的定时任务机制已经不仅仅应用于数据复制,数据库管理员也常使用定时任务来作一些对数据库的日常维护任务,在实际应用中也可用来安排一些繁重的批处理任务在数据库系统不忙时执行,还可用于启动监听数据库管道的服务程序,用来响应用户会话的服务请求等等。下面将详细讨论Oralce 的定时任务机制。

  DBMS_JOB系统包是Oracle“任务队列”子系统的API编程接口。DBMS_JOB包对于任务队列提供了下面这些功能:提交并且执行一个任务、改变任务的执行参数以及删除或者临时挂起任务等。

  DBMS_JOB包是由ORACLE_HOME目录下的rdbms/admin子目录下的DBMSJOB.SQL和PRVTJOB.PLB 这两个脚本文件创建的。这两个文件被CATPROC.SQL脚本文件调用,而CATPROC.SQL这个文件一般是在数据库创建后立即执行的。脚本为DBMS_JOB包创建了一个公共同义词,并给该包授予了公共的可执行权限,所以所有的Oracle用户均可以使用这个包。

  最后,要使任务队列能正常运行,还必须启动它自己专有的后台过程。启动后台过程是通过在初始化文件init*.ora(实例不同,初始化文件名也略有不同)中设置初始化参数来进行的。下面就是该参数:

  其中,n可以是0到36之间的任何一个数。除了该参数以外,还有几个关于任务队列的初始化参数,本文后面将会对其进行详细讨论。

  DBMS_JOB包中所有的过程都有一组相同的公共参数,用于定义任务,任务的运行时间以及任务定时运行的时间间隔。这些公共任务定义参数见表2所示。

  job是一个整数,用来唯一地标示一个任务。该参数既可由用户指定也可由系统自动赋予,这完全取决于提交任务时选用了那一个任务提交过程。DBMS_JOB.SUBMIT过程通过获得序列SYS.JOBSEQ的下一个值来自动赋予一个任务号。该任务号是作为一个OUT参数返回的,所以调用者随后可以识别出提交的任务。而DBMS_JOB.ISUBMIT过程则由调用者给任务指定一个识别号,这时候,任务号的唯一性就完全取决于调用者了。

  除了删除或者重新提交任务,一般来说任务号是不能改变的。即使当数据库被导出或者被导入这样极端的情况,任务号也将被保留下来。所以在执行含有任务的数据的导入/导出操作时很可能会发生任务号冲突的现象。

  what参数是一个可以转化为合法PL/SQL调用的字符串,该调用将被任务队列自动执行。在what参数中,如果使用文字字符串,则该字符串必须用单引号括起来。 what参数也可以使用包含我们所需要字符串值的VARCHAR2变量。实际的PL/SQL调用必须用分号隔开。在PL/SQL调用中如果要嵌入文字字符串,则必须使用两个单引号。

  what参数的长度在Oracle7.3中限制在2000个字节以内,在Oracle 8.0以后,扩大到了4000个字节,这对于一般的应用已完全足够。该参数的值一般情况下都是对一个PL/SQL存储过程的调用。在实际应用中,尽管可以使用大匿名Pl/SQL块,但建议大家最好不要这样使用。还有一个实际经验就是最好将存储过程调用封装在一个匿名块中,这样可以避免一些比较莫名错误的产生。我来举一个例子,一般情况下,what参数可以这样引用:

  任何时候,我们只要通过更改what参数就可以达到更改任务定义的目的。但是有一点需要注意,通过改变what参数来改变任务定义时,用户当前的会话设置也被记录下来并成为任务运行环境的一部分。如果当前会话设置和最初提交任务时的会话设置不同,就有可能改变任务的运行行为。意识到这个潜在的副作用是非常重要的,无论何时只要应用到任何DBMS_JOB过程中的what参数时就一定要确保会线、next_date Next_

  date参数是用来调度任务队列中该任务下一次运行的时间。这个参数对于DBMS_JOB.SUBMIT和DBMS_JOB.BROKEN这两个过程确省为系统当前时间,也就是说任务将立即运行。

  当将一个任务的next_date参数赋值为null时,则该任务下一次运行的时间将被指定为4000年1月1日,也就是说该任务将永远不再运行。在大多数情况下,这可能是我们不愿意看到的情形。但是,换一个角度来考虑,如果想在任务队列中保留该任务而又不想让其运行,将next_date设置为null却是一个非常简单的办法。

  Internal参数是一个表示Oracle合法日期表达式的字符串。这个日期字符串的值在每次任务被执行时算出,算出的日期表达式有两种可能,要么是未来的一个时间要么就是null.这里要强调一点:很多开发者都没有意识到next_date是在一个任务开始时算出的,而不是在任务成功完成时算出的。

  当任务成功完成时,系统通过更新任务队列目录表将前面算出的next_date值置为下一次任务要运行的时间。当由interval表达式算出next_date是null时,任务自动从任务队列中移出,不会再继续执行。因此,如果传递一个null值给interval参数,则该任务仅仅执行一次。

  任务队列在Oracle系统中其实是一个子系统,它具有自己特定的后台过程和目录表。该子系统设计的目的是为了能不在用户干预下自动运行PL/SQL过程。

  任务队列(SNP)后台过程随着Oracle实例的启动而同时启动。在文章前面已经谈到初始化文件init.ora中的参数JOB_QUEUE_PROCESSES,用来设置有几个队列过程。这里设置了几个过程,系统中就会有几个SNP过程被启动。JOB_QUEUE_PROCESSES这个参数,可以是0到36中的任何一个数,也就是说对于每个Oracle实例最多可以有36个SNP过程,也可以不支持队列过程(=0)。在大多数操作系统中,SNP三个字母常作为过程名的一部分出现。如,在unix系统中,如果该Oracle实例名为ora8,有三个任务队列过程,则这三个任务队列过程名称为:

  参数初始化文件init.ora中的几个参数控制着任务队列后台的运行,下面我们将对其进行详细讨论。

  任务队列过程定期唤醒并检查任务队列目录表是否有任务需要执行。参数JOB_QUEUE_INTERVAL决定SNP过程两次检查目录表之间“休眠”多长时间(单位为秒)。间隔设的太小会造成由于SNP过程不断检查目录表而导致不必要的系统吞吐量。相反如果间隔设得太大,SNP过程在特定的时间没有被唤醒,那个时间的任务就不会能被运行。最佳的时间间隔设置要综合考虑系统环境中不同的任务,60秒的确省设置可以满足大多数的应用。

  除了前面介绍的JOB_QUEUE_PROCESS和JOB_QUEUE_INTERVAL两个参数以外,影响SNP后台过程行为的第三个参数是JOB_QUEUE_KEEP_CONNECTIONS.当该参数为TRUE时,SNP过程在两个任务的运行期间(也就是休眠期间),仍然和Oracle保持开放的连接。相反,如果为FALSE时,SNP过程将和数据库断开连接,当唤醒时刻到来时又重新连接并检查任务队列。

  选择这两种方法中的那一种,主要是考虑任务队列的有效性和数据库关闭方法。长期保持连接的效率比较高,但任务队列会受到正常关闭数据库的影响。这是因为任务队列过程对于服务器管理器看来和一个普通用户的过程没有什么不同,而正常的关闭数据库需要让所有的用户都断开连接。而断开连接和重新连接又给数据库增加了负荷,但是可定期地使数据库没有可连接SNP过程,也就可以使数据库正常关闭。对于有很多任务或者是任务重复执行的时间间隔较短(一个小时或者更少)的环境,一般将JOB_QUEUE_KEEP_CONNECTIOONS设置为TRUE,并修改关闭数据库的脚本为立即关闭。对于严格要求采用正常方式关闭的数据库或者是任务较少,重复间隔较长的环境,一般将该参数设置为FALSE.最好,要提醒一句,SNP过程仅在没有任何任务运行时才断开,这种情况下,那些需要比较长时间运行的任务SNP将在它们的生命周期内一致保持开放的连接,这就延迟了正常关闭数据库的时间。

  当SNP过程唤醒时,它首先查看任务队列目录中所有的任务是否当前的时间超过了下一次运行的日期时间。SNP检测到需要该时间立即执行的任务后,这些任务按照下一次执行日期的顺序依次执行。当SNP过程开始执行一个任务时,其过程如下:

  在前两步中,SNP过程创建了一个模仿用户运行任务定义的PL/SQL的会话环境。然而,这个模仿的运行环境并不是和用户实际会话环境完全一样,需要注意以下两点:第一,在任务提交时任何可用的非确省角色都将在任务运行环境中不可用。因此,那些想从非确省角色中取得权限的任务不能提交,用户确省角色的修改可以通过在任务未来运行期间动态修改来完成。第二,任何任务定义本身或者过程执行中需要的数据库联接都必须完全满足远程的用户名和密码。SNP过程不能在没有显式指明口令的情况下初始化一个远程会话。显然,SNP过程不能假定将本地用户的口令作为远程运行环境会话设置的一部分。

  提交的任务如果运行失败会怎么样呢?当任务运行失败时,SNP过程在1分钟后将再次试图运行该任务。如果这次运行又失败了,下一次尝试将在2分钟后进行,再下一次在4分钟以后。任务队列每次加倍重试间隔直到它超过了正常的运行间隔。在连续16次失败后,任务就被标记为中断的(broken),如果没有用户干预,任务队列将不再重复执行。

  任务队列中的任务信息可以通过表3所示的几个字典视图来查看,这些视图是由CATJOBQ.sql脚本创建的。表4和5是各个视图每个字段的含义。

  算法任务重复运行的时间间隔取决于interval参数中设置的日期表达式。下面就来详细谈谈该如何设置interval参数才能准确满足我们的任务需求。一般来讲,对于一个任务的定时执行,有三种定时要求。

  表6所示的任务间隔表达式不能保证任务的下一次运行时间在一个特定的日期或者时间,仅仅能够指定一个任务两次运行之间的时间间隔。例如,如果一个任务第一次运行是在凌晨12点,interval指定为SYSDATE + 1,则该任务将被计划在第二天的凌晨12点执行。但是,如果某用户在下午4点手工(DBMS_JOB.RUN)执行了该任务,那么该任务将被重新定时到第二天的下午4点。还有一个可能的原因是如果数据库关闭或者说任务队列非常的忙以至于任务不能在计划的那个时间点准时执行。在这种情况下,任务将试图尽快运行,也就是说只要数据库一打开或者是任务队列不忙就开始执行,但是这时,运行时间已经从原来的提交时间漂移到了后来真正的运行时间。这种下一次运行时间的不断“漂移”是采用简单时间间隔表达式的典型特征。

  Oracle中的定时任务是在Oracle系统中是一个非常重要的子系统,运用得当,可以极大的提高我们的系统运行和维护能力。而Oracle数据复制的延迟事务队列管理完全是基于Oracle的队列任务,对其的深刻理解有助于我们更好地管理数据复制。

http://magazinski.com/ziduilie/244.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有