ORACLE架构及各进程

. 进程概述php

       先来看一下Oracle 11g 的架构图。 算法

下载地址:Oracle 11g 架构图 from Oracle University数据库

 

  

      

       进程是操做系统中的一种机制,它可执行一系列的操做步。在有些操做系统中使用做业(JOB)或任务(TASK)的术语。一个进程一般有它本身的专用存储区。ORACLE进程的体系结构设计使性能最大。

ORACLE实例有两种类型:单进程实例 多进程实例


       单进程ORACLE(又称单用ORACLE)是一种数据库系统,一个进程执行所有ORACLE代码。因为ORACLE部分和客户应用程序不能分别以进程执行,因此ORACLE的代码和用户的数据库应用是单个进程执行。在单进程环境下的ORACLE 实例,仅容许一个用户可存取。例如在MS-DOS上运行ORACLE


       多进程ORACLE实例(又称多用户ORACLE)使用多个进程来执行ORACLE的不一样部分 ,对于每个链接的用户都有一个进程。
       在多进程系统中,进程分为两类:用户进程 ORACLE进程。当一用户运行一应用程序,如PRO*C程序或一个ORACLE工具(如SQL*PLUS),为用户运行的应用创建一个用户进程。
缓存

 

ORACLE进程又分为两类:服务器进程 后台进程安全

服务器进程用于处理链接到该实例的用户进程的请求。当应用和ORACELE是在同一台机器上运行,而再也不经过网络,通常将用户进程和它相应的服务器进程组合成单个的进程,可下降系统开销。然而,当应用和ORACLE运行在不一样的机器上时,用户进程通过一个分离服务器进程与ORACLE通讯。它可执行下列任务:
       1) 对应用所发出的SQL语句进行语法分析和执行。

       2) 从磁盘(数据文件)中读入必要的数据块到SGA的共享数据库缓冲区(该块不在缓冲区时)。

       3) 将结果返回给应用程序处理。


       系统为了使性能最好和协调多个用户,在多进程系统中使用一些附加进程,称为后台进程。在许多操做系统中,后台进程是在实例启动时自动地创建。一个ORACLE实例能够有许多后台进程,但它们不是一直存在。
服务器

 

后台进程有:
DBWR(Database Write) : 数据库写入程序
LGWR(Log Write) : 日志写入程序
CKPT(Checkpoint) : 检查点
SMON (System Monitor): 系统监控

PMON(Process Monitor) : 进程监控

ARCH(Archive) : 归档

RECO : 恢复
LCKn : 封锁;


这是RAC 环境启动时,各个进程的启动顺序:
网络

PMON started with pid=2, OS id=18042架构

DIAG started with pid=3, OS id=18044并发

PSP0 started with pid=4, OS id=18051oracle

LMON started with pid=5, OS id=18053

LMD0 started with pid=6, OS id=18055

LMS0 started with pid=7, OS id=18057

MMAN started with pid=8, OS id=18061

DBW0 started with pid=9, OS id=18063

LGWR started with pid=10, OS id=18065

CKPT started with pid=11, OS id=18067

SMON started with pid=12, OS id=18069

RECO started with pid=13, OS id=18071

CJQ0 started with pid=14, OS id=18073

MMON started with pid=15, OS id=18075

MMNL started with pid=16, OS id=18077

       每一个后台进程与ORACLE数据库的不一样部分交互。 其中SMONPMONDBWnCKPTLGWR  是五个必须的ORACLE后台进程。

 

. 进程详细说明

1. DBWR进程

       该进程执行将缓冲区写入数据文件,是负责缓冲存储区管理的一个ORACLE后台进程。当缓冲区中的一缓冲区被修改,它被标志为弄脏DBWR的主要任务是将弄脏的缓冲区写入磁盘,使缓冲区保持干净。因为缓冲存储区的缓冲区填入数据库或被用户进程弄脏,未用的缓冲区的数目减小。当未用的缓冲区降低到不多,以至用户进程要从磁盘读入块到内存存储区时没法找到未用的缓冲区时,DBWR将管理缓冲存储区,使用户进程总可获得未用的缓冲区。

       ORACLE采用LRULEAST RECENTLY USED)算法(最近最少使用算法)保持内存中的数据块是最近使用的,使I/O最小。

触发DBWR进程的条件有:
              1.  DBWR超时,大约3
              2.  系统中没有多余的空缓冲区来存放数据

              3.  CKPT 进程触发
DBWR
       在有些平台上,一个实例可有多个DBWR。在这样的实例中,一些块可写入一磁盘,另外一些块可写入其它磁盘。

 

2. LGWR进程

       该进程将日志缓冲区写入磁盘上的一个日志文件,它是负责管理日志缓冲区的一个ORACLE后台进程。

 

触发LGWR进程的条件有:
  1. 用户提交
  2. 1/3重作日志缓冲区未被写入磁盘

  3. 有大于1M的重作日志缓冲区未被写入磁盘

  4. 3秒超时

  5. DBWR 须要写入的数据的SCN大于LGWR记录的SCNDBWR 触发LGWR写入。


       日志缓冲区是一个循环缓冲区。当LGWR将日志缓冲区的日志项写入日志文件后,服务器进程可将新的日志项写入到该日志缓冲区。LGWR 一般写得很快,可确保日志缓冲区总有空间可写入新的日志项。

注意:有时候当须要更多的日志缓冲区时,LWGR在一个事务提交前就将日志项写出,而这些日志项仅当在之后事务提交后才永久化。


       ORACLE使用快速提交机制,当用户发出COMMIT语句时,一个COMMIT记录当即放入日志缓冲区,但相应的数据缓冲区改变是被延迟,直到在更有效时才将它们写入数据文件。当一事务提交时,被赋给一个系统修改号(SCN),它同事务日志项一块儿记录在日志中。因为SCN记录在日志中,以至在并行服务器选项配置状况下,恢复操做能够同步。


3. CKPT进程

       该进程在检查点出现时,对所有数据文件的标题进行修改,指示该检查点。负责在每当缓冲区高速缓存中的更改永久地记录在数据库中时,更新控制文件和数据文件中的数据库状态信息。

 

RedoLog Checkpoint SCN关系

http://blog.csdn.net/tianlesoftware/archive/2010/01/25/5251916.aspx

 

Redo Log Checkpoint not complete

http://blog.csdn.net/tianlesoftware/archive/2009/12/01/4908066.aspx


4. SMON进程

       SMONOracle数据库相当重要的一个后台进程, 该进程实例启动时执行实例恢复,还负责清理再也不使用的临时段, 是一种用于库的垃圾收集者。在具备并行服务器选项的环境下,SMON对有故障CPU或实例进行实例恢复。SMON进程有规律地被呼醒,检查是否须要,或者其它进程发现须要时能够被调用。

 

它作的工做包括以下7件:

       1)清理临时表空间:伴随这真正的临时表空间的出现,清理临时表空间的琐事已经减轻了,但它还没彻底消失。例如,当创建一个索引,在建立期间分配给索引的扩展区被标志为TEMPORARY。若是Create Index会话因某些缘由异常中断,SMON负责清理他们。其余操做建立的临时扩展区,SMON一样会负责。
       2 接合空闲空间:若是你正使用数据字典管理表空间,SMON负责把那些在表空间中空闲的而且互相是邻近的extent接合成一个较大的空闲扩展区。这发生仅在带有默认的pctincrease设置为非零的存储子句的字典管理表空间。
       3 把对于不可用文件的事务恢复成活动状态:它的角色相似在库启动期间。这时,由于文件不能用于恢复,SMON恢复在实例/崩溃恢复期间被跳过的故障事务。例如,文件可能已经在不可用或没装载的磁盘上。当文件变可用了,SMON将恢复它。
       4)执行一个RAC中故障节点的实例恢复:在一个oracle RAC配置中,当群集中的一个库实例失败(例如,实例正执行的机器故障了),一些群集中的其余节点将开启故障的实例的重作日志文件,为故障实例执行全部数据的恢复。
       5)清理OBJ$OBJ$是一个包含库中几乎每个对象(表,索引,触发器,视图等等)的记录的行级数据字典表。许屡次,这儿存在的记录表明已删对象,或表明不在这儿的对象,在oracle的信赖机制中被使用。SMON是删除这些不在被须要的行的进程。
       6)收缩回滚段:SMON将执行回滚段的自动收缩到它的optimal尺寸,若是它被设置。
       7脱机回滚段:对于DBA来,让一个有active事务的回滚段,脱机或不可用,这事是可能的。Active事务正使用这脱机回滚段是可能的。在这状况下,回滚不是真正的脱机;它被标志为悬挂offline”。在后台进程中,SMON将周期性尽力让它真正脱机,直到成功。

       SMON作许多其余事情,譬如存在DBA_TAB_MONITORING视图中的监控统计数据的洗刷,SMON_SCN_TIME表中发现的时间戳定位信息的SCN的洗刷,等等。SMON在期间能消耗不少CPU,这应该被认为是正常的。SMON周期性的苏醒(或被其余后台进程叫醒)来执行这些管家的家庭琐事。

 

5. PMON进程

       用于恢复失败的数据库用户的强制性进程,它先获取失败用户的标识,释放该用户占有的全部数据库资源。PMON有规律地被呼醒,检查是否须要,或者其它进程发现须要时能够被调用。

 

       PMON进程负责在反常中断的链接以后的清理工做。例如,若是因某些缘由专用服务故障或被kill掉,PMON就是负责处理(恢复或回滚工做)和释放你的资源。       PMON将发出未提交工做的回滚,释放锁,和释放分配给故障进程的SGA资源。除了在异常中断以后的清理外,PMON监控其余oracle后台进程,若是有必要(和有可能)从新启动他们。若是共享服务或一个分配器故障(崩溃),PMON将插手而且重启另外一个(在清理故障进程以后)。

       PMON将观察全部Oracle进程,只要合适或重启他们或停止进程。例如,在数据库日志写进程事件中,LGWR故障,实例故障。这是一个严重的错误,最安全的处理方法就是去当即终止实例,让正常的恢复处理数据。

       PMON为实例作的另外一件事是去使用Oracle TNS监听器登记。当一个实例开启的时候,PMON进程投出众所周知的端口地址,除非指向其余,来看是否监听器正在开和运行着。众所周知/默认端口是使用1521

       如今,若是监听器在一些不一样端口开启会发生什么?这种状况,机制是相同的,除了监听器地址须要被LOCAL_LISTENER参数明确指定。若是监听器运行在库实例开启的时候,PMON和监听器通信,传到它相关参数,譬如服务器名和实例的负载度量。若是监听器没被开启,PMON将周期性的试着和它联系来登记本身。

 

The background process PMON cleans up after failed processes by:
       1. Rolling back the user’s current transaction
       2. Releasing all currently held table or row locks
       3. Freeing other resources currently reserved by the user
       4. Restarts dead dispatchers

 

6. RECO进程

       负责在分布式数据库环境中自动恢复那些失败的分布式事务,保证分布式事务的一致性,在分布式事务中,要么同时commit,要么同时rollback;

 

7. ARCH进程

       该进程将已填满的在线日志文件拷贝到指定的存储设备。当数据库运行在归档模式下,归档进程负责在日志切换后将已经写满的重作日志文件复制到归档目标.


8. LCKn进程

       是在具备并行服务器选件环境下使用,可多至10个进程(LCK0LCK1……LCK9),用于实例间的封锁。

 

9. MMAN 进程

       内存管理,若是设定了 SGA自动管理,MMAN用来协调SGA内各组件的大小设置和大小调整。

 

10. MMON 进程

       管理性监视器(Manageability Monitor),MMON主要用于AWRADDMMMON会从SGA将统计结果写到系统表中。

        MMON: The Manageability Monitor (MMON) process was introduced in 10g and  is associated with the Automatic Workload Repository new features used  for automatic problem detection and self-tuning. MMON writes out the  required statistics for AWR on a scheduled basis.

 

 

.  DBWRCKPTLGWR进程之间的关系

将内存数据块写入数据文件实在是一个至关复杂的过程,在这个过程当中,首先要保证安全。所谓安全,就是在写的过程当中,一旦发生实例崩溃,要有一套完整的机制可以保证用户已经提交的数据不会丢失;其次,在保证安全的基础上,要尽量的提升效率。众所周知,I/O操做是最昂贵的操做,因此应该尽量的将脏数据块收集到必定程度之后,再批量写入磁盘中。

 

直观上最简单的解决方法就是,每当用户提交的时候就将所改变的内存数据块交给DBWR,由其写入数据文件。这样的话,必定可以保证提交的数据不会丢失。可是这种方式效率最为低下,在高并发环境中,必定会引发I/O方面的争用。oracle固然不会采用这种没有扩展性的方式。oracle引入了CKPTLGWR这两个后台进程,这两个进程与DBWR进程互相合做,提供了既安全又高效的写脏数据块的解决方法。

 

   用户进程每次修改内存数据块时,都会在日志缓冲区(redo buffer)中构造一个相应的重作条目(redo entry),该重作条目描述了被修改的数据块在修改以前和修改以后的值。而LGWR进程则负责将这些重作条目写入联机日志文件。只要重作条目进入了联机日志文件,那么数据的安全就有保障了,不然这些数据都是有安全隐患的。LGWR是一个必须和前台用户进程通讯的进程。LGWR承担了维护系统数据完整性的任务,它保证了数据在任何状况下都不会丢失。

 

   LGWR将重作条目写入联机日志文件的状况分两种:后台写(background write同步写(sync write

触发后台写的条件有四个:

1)每隔三秒钟,LGWR启动一次;

2)DBWR启动时,若是发现脏数据块所对应的重作条目尚未写入联机日志文件,则DBWR触发LGWR进程并等待LRWR写完之后才会继续;

3)重作条目的数量达到整个日志缓冲区的1/3时,触发LGWR

4)重作条目的数量达到1MB时,触发LGWR

 

触发同步写的条件就一个:当用户提交(commit)时,触发LGWR

 

  假如DBWR在写脏数据块的过程当中,忽然发生实例崩溃。咱们已经知道,用户提交时,oracle是不必定会把提交的数据块写入数据文件的。那么实例崩溃时,必然会有一些已经提交可是尚未被写入数据文件的内存数据块丢失了。当实例再次启动时,oracle须要利用日志文件中记录的重作条目在buffer cache中从新构造出被丢失的数据块,从而完成前滚和回滚的工做,并将丢失的数据块找回来。因而这里就存在一个问题,就是oracle在日志文件中找重作条目时,到底应该找哪些重作条目?换句话说,应该在日志文件中从哪一个起点开始日后应用重作条目?注意,这里所指的日志文件可能不止一个日志文件。

 

由于oracle须要随时预防可能的实例崩溃现象,因此oracle数据库的 正常运行过程当中,会不断的定位这个起点,以便在不可预期的实例崩溃中可以最有效的保护并恢复数据。同时,这个起点的选择很是有讲究。首先,这个起点不能太 靠前,太靠前意味着要处理不少的重作条目,这样会致使实例再次启动时所进行的恢复的时间太长;其次,这个起点也不能太靠后,太靠后说明只有不多的脏数据块 没有被写入数据文件,也就是说前面已经有不少脏数据块被写入了数据文件,那也就意味着只有在DBWR启动的很频繁的状况下,才能使得buffer cache中所残留的脏数据块的数量不多。但很明显,DBWR启动的越频繁,那么所占用的写数据文件的I/O就越严重,那么留给其余操做(好比读取buffer cache中不存在的数据块等)的I/O资源就越少。这显然也是不合理的。

从这里也能够看出,这个起点实际上说明了,在日志文件中位于这个起点以前的重作条目所对应的在buffer cache中 的脏数据块已经被写入了数据文件,从而在实例崩溃之后的恢复中不须要去考虑。而这个起点之后的重作条目所对应的脏数据块实际尚未被写入数据文件,若是在 实例崩溃之后的恢复中,须要从这个起点开始日后,依次取出日志文件中的重作条目进行恢复。考虑到目前的内存容量愈来愈大,buffer cache也愈来愈大,buffer cache中包含几百万个内存数据块也是很正常的现象的前提下,如何才能最有效的来定位这个起点呢?

 

为了可以最佳的肯定这个起点,oracle引入了名为CKPT的后台进程,一般也叫做检查点进程(checkpoint process。这个进程与DBWR共同合做,从而肯定这个起点。同时,这个起点也有一个专门的名字,叫作检查点位置(checkpoint position

oracle为了在检查点的算法上更加的具备可扩展性(也就是为了可以在巨大的buffer cache下依然有效工做),引入了检查点队列(checkpoint queue,该队列上串起来的都是脏数据块所对应的buffer header

DBWR每次写脏数据块时,也是从检查点队列上扫描脏数据块,并将这些脏数据块实际写入数据文件的。当写完之后,DBWR会将这些已经写入数据文件的脏数据块从检查点队列上摘下来。这样即使是在巨大的buffer cache下工做,CKPT也可以快速的肯定哪些脏数据块已经被写入了数据文件,而哪些尚未写入数据文件,显然,只要在检查点队列上的数据块都是尚未写入数据文件的脏数据块。

为了更加有效的处理单实例和多实例(RAC)环境下的表空间的检查点处理,好比将表空间设置为离线状态或者为热备份状态等,oracle还专门引入了文件队列(file queue。文件队列的原理与检查点队列是同样的,只不过每一个数据文件会有一个文件队列,该数据文件所对应的脏数据块会被串在同一个文件队列上;同时为了可以尽可能减小实例崩溃后恢复的时间,oracle还引入了增量检查点(incremental checkpoint,从而增长了检查点启动的次数。

若是每次检查点启动的间隔时间过长的话,再加上内存很大,可能会使得恢复的时间过长。由于前一次检查点启动之后,标识出了这个起点。而后在第二次检查点启动的过程当中,DBWR可能已经将不少脏数据块已经写入了数据文件,而假如在第二次检查点启动以前发生实例崩溃,致使在日志文件中,所标识的起点仍然是上一次检查点启动时所标识的,致使oracle不知道这个起点之后的不少重作条目所对应的脏数据块实际上已经写入了数据文件,从而使得oracle在实例恢复时再次重复的处理一遍,效率低下,浪费时间。

 

上面说到了有关CKPT的两个重要的概念:检查点队列(包括文件队列)和增量检查点

检查点队列在咱们上面转储出来的buffer header里能够看到,就是相似ckptq: [65abceb4,63bec66c]fileq: [65abcfbc,63becd10]的结构,记录的一样都是指向前一个buffer header和指向后一个buffer header的指针。这个队列上面挂的也是脏数据块对应的buffer header链表,可是它与LRUW链表不一样。检查点队列上的buffer header是按照数据块第一次被修改的时间的前后顺序来排列的。越早修改的数据块的buffer header排在越前面,同时若是一个数据块被修改了屡次的话,在该链表上也只出现一次。并且,检查点队列上的buffer header还记录了脏数据块在第一次被修改时,所对应的重作条目在重作日志文件中的地址,也就是RBARedo Block Address)。一样在转储出来的buffer header中能够看到相似LRBA: [0xe9.229.0]的结构,这就是RBAL表示Low,也就是第一次被修改的时候的RBA。可是注意,在检查点队列上的buffer header,并不表示必定会有一个对应的RBA,好比控制文件重作(controlfile redo)就不会有相应的RBA。对于没有对应RBAbuffer header来讲,在检查点队列上始终处于最尾端,其优先级永远比有RBA的脏数据块的buffer header要低。8i之前,每一个working set都有一个检查点队列以及多个文件队列(由于一个数据文件对应一个文件队列);而从8i开始,每一个working set都有两个检查点队列,每一个检查点都会由checkpoint queue latch来保护。

增量检查点是从8i开始出现的,是相对于8i以前的彻底检查点(complete checkpoint)而言的。彻底检查点启动时,会标识出buffer cache中全部的脏数据块,而后启动DBWR进程将这些脏数据块写入数据文件。8i以前,日志切换的时候会触发彻底检查点。

而到了8i及之后,彻底检查点只有在两种状况下才会被触发:

1)发出命令:alter system checkpoint

2)除了shutdown abort之外的正常关闭数据库。

注意,这个时候,日志切换不会触发彻底检查点,而是触发增量检查点。8i所引入的增量检查点每隔三秒钟或发生日志切换时启动。它启动时只作一件事情:找出当前检查点队列上的第一个buffer header,并将该buffer header中所记录的LRBA(这个LRBA也就是checkpoint position了)记录到控制文件中去。若是是由日志切换所引发的增量检查点,则还会将checkpoint position记录到每一个数据文件头中。也就是说,若是这个时候发生实例崩溃,oracle在下次启动时,就会到控制文件中找到这个checkpoint position做为在日志文件中的起点,而后从这个起点开始向后,依次取出每一个重作条目进行处理。

上面所描述的概念,用一句话来归纳,其实就是DBWR负责写检查点队列上的脏数据块,而CKPT负责记录当前检查点队列的第一个数据块所对应的的重作条目在日志文件中的地址。从这个意义上说,检查点队列比LRUW还要重要,LRUW主要就是区分出哪些数据块是脏的,不能够被重用的。而到底应该写哪些脏数据块,写多少脏数据块,则仍是要到检查点队列上才能肯定的。

 

       咱们用一个简单的例子来描述这个过程。假设系统中发生了一系列的事务,致使日志文件以下所示:

 

事务号  数据文件号  block   行号       RBA

T1     8         25        10    1  10    101

T1     7         623       12    2  a     102

T3     8         80        56    3  b     103

T3     9         98        124   7  e     104

T5     7         623       13    3  abc   105

Commit SCN#    timestamp                  106

T123   8         876       322   10 89    107

 

       这时,对应的检查点队列则相似以下图六所示。咱们能够看到,T1事务最早发生,因此位于检查点

图六

 

       队列的首端,而事务T123最后发生,因此位于靠近尾端的地方。同时,能够看到事务T1T5都更新了7号数据文件的623号数据块。而在检查点队列上只会记录该数据块的第一次被更新时的RBA,也就是事务T1对应的RBA102,而事务T5对应的RBA105并不会被记录。由于根本就不须要在检查点队列上记录。当DBWR写数据块的时候,在写RBA102时,天然就把RBA105所修改的内容写入数据文件了。日志文件中所记录的提交标记也不会体如今检查点队列上,由于提交自己只是一个标记而已,不会涉及到修改数据块。

       这时,假设发生三秒钟超时,因而增量检查点启动。增量检查点会将检查点队列的第一个脏数据块所对应的RBA记录到控制文件中去。在这里,也就是RBA101会做为checkpointposition记录到控制文件中。

       而后,DBWR后台进程被某种条件触发而启动。DBWR根据一系列参数及规则,计算出应该写的脏数据块的数量,从而将RBA101RBA107之间的这5个脏数据块写入数据文件,并在写完之后将这5个脏数据块从检查点队列上摘除,而留下了4个脏数据块在检查点队列上。若是在写这5个脏数据块的过程当中发生实例崩溃,则下次实例启动时,oracle会从RBA101开始应用日志文件中的重作条目。

图七

 

       而在9i之后,在DBWR写完这5个脏数据块之后,还会在日志文件中记录所写的脏数据块的块号。以下图所示。这主要是为了在恢复时加快恢复的速度。

图八

      

       这时,又发生三秒钟超时,因而增量检查点启动。这时它发现checkpointpositionRBA109,因而将RBA109写入控制文件。若是接着发生实例崩溃,则oracle在下次启动时,就会从RBA109开始应用日志。

相关文章
相关标签/搜索