Oracle从新手到高手
上QQ阅读APP看书,第一时间看更新

2.5 实例的进程结构

进程是操作系统中一个独立的可以调度的活动,用于完成指定的任务。进程与程序的区别在于前者是一个动态概念,后者是一个静态实体。程序仅是指令的有序集合,而进程则强调执行过程。进程可以动态创建,当完成任务后即会消亡。

在Oracle系统工作过程中,主要涉及如下3类进程。

※ 用户进程:在用户连接数据库时会创建一个用户进程。用户进程执行的是一个应用程序或Oracle工具程序的代码,以完成用户指定的任务。用户进程不是实例的组成部分。

※ 服务器进程:这些进程根据客户的请求来完成工作。

※ 后台进程:这些进程随数据库而启动,用于完成各种维护任务,如将数据块写入磁盘进程DBWR、维护在线重做日志进程LGWR、清理异常中止的进程等。

下图展示了服务器进程、用户进程和后台进程之间的关系。

2.5.1 用户进程

当用户执行一个Oracle应用程序时,或者启动一个Oracle工具时(如SQL*Plus),Oracle将创建一个用户进程来执行相应的用户任务。与用户进程相关的有两个概念—连接和会话。

连接是一个用户进程与数据库实例之间的一条通信路径,这条通信路径通过操作系统平台中的进程之间的通信机制或网络连接来实现;会话则是一个用户到数据库的指定连接,例如当一个用户启动SQL*Plus,并输入正确的用户名和密码连接一个数据库后,就为该用户创建了一个会话。会话在用户连接实例的过程中始终存在,直到用户断开连接或终止应用程序为止。

可以看出,会话是通过连接来建立的。同一个用户可以通过建立多个连接来创建到Oracle数据库的多个会话。例如,一个用户可以使用同一个账户启动多个SQL*Plus程序来对数据库进行操作。可以在SQL*Plus中查询动态性能视图V$SESSION来查看实际的会话。

2.5.2 服务器进程

服务器进程就是代表用户会话完成工作的进程,应用向数据库发送的SQL语句就是由这些进程接收并执行的。在Oracle数据库中可以同时存在两种类型的服务器进程:一种是专用服务器进程,一个专用服务进程只能为一个用户进程提供服务;另一种是共享服务进程,一个共享服务进程可以为多个用户进程提供服务。

专用服务器进程和共享服务器进程的任务是相同的。

※ 解析并执行用户所提交的SQL语句。

※ 在SGA区的数据缓存区中搜索用户进程所访问的数据;如果数据不在缓存中,则需要从硬盘数据文件中读取所需的数据,再将其复制到缓存中。

※ 将数据返回给用户进程。

2.5.3 后台进程

Oracle实例包括两部分:SGA和一组后台进程。在任意时刻,Oracle数据库可以处理多个并发用户请求,进行复杂的数据操作,与此同时还要维护数据库系统使其始终具有良好的性能。为了完成这些任务,Oracle具有一组后台进程保证数据库运行所需的实际维护任务。

可以使用一个V$BGPROCESS视图查看所有可能的Oracle后台进程,下图展示了有一个中心用途的Oracle后台进程。

启动实例时并不会看到所有这些进程,有一些进程只有在特殊情况下才会存在。例如,当数据库在归档模式下,则会启用归档进程ARCn;如果运行了Oracle RAC,这种Oracle配置允许一个集群中不同计算机上的多个实例装载并打开相同的物理数据库,这时就会启动LMD0、LCKn、LMON和LMSn等进程,只有DBWR、LGWR、CKPT、SMON和PMON等进程是实例所必需的。本节将介绍Oracle实例中常见的一些后台进程。

1. DBWR(数据写进程)

数据写进程DBWR负表将缓存区中的数据写入数据文件,它是管理缓存区的一个Oracle后台进程。当数据缓存区中某个缓冲块的数据被修改时,它被标志为“弄脏”。DBWR的主要任务是将“弄脏”的缓存块的数据写入磁盘,使缓冲区保持“干净”。需要注意,只有在满足一定的条件时,DBWR进程才开始成批地将脏缓存块写入数据文件,这样做能够尽量避免DBWR进程与其他进程之间发生I/O冲突,并且减少数据库执行物理I/O操作的次数。

另外,DBWR进程也不是将所有的脏缓存块写入数据文件,因为脏缓存块一旦被写入数据文件,它将被标记为空闲缓存块,其中保存的数据将丢失。如果随后立即有其他的用户进程需要访问脏缓存块中以前所保存的数据,Oracle需要重新到数据文件中读取数据。为了避免这样的缓存失败,可以通过LRU算法解决这个问题,将那些经常被访问的脏缓存块继续保留在缓存中,而将最近未被访问过的缓存块标记为“冷缓存块”,DBWR进程只将那些同时被标记为“脏”和“冷”的缓存块写入数据文件。

只有发生下列情况时,DBWR进程才开始将脏缓存块写入数据文件。

※ 当用户进程执行INSERT和UPDATE等操作时,会首先将插入的数据写入数据缓存。在这个过程中,如果Oracle在数据缓存的LRU列表中搜索了一定数量的缓存块后,仍然没有找到可用的空闲缓存块,DBWR进程被启动。由DBWR进程将脏缓存块写入数据文件,以获得更多的空闲缓存块。

※ 当出现检查点时,LGWR将通知DBWR进行写操作。

※ 当将缓存区的脏数据块移入脏列表时,如果脏列表达到临界长度时,将通知DBWR将脏数据块写入数据文件。该临界长度为初始化参数DB_ BLOCK_WRITE_BATCH的50%。

※ 若出现超时(3s内未被启动),DBWR进程将被启动。

DBWR进程的启动时间对整个Oracle数据库的性能有很大影响。如果DBWR进程过于频繁地启动,将降低整个系统的I/O性能。但如果DBWR进程间隔很久才启动一次,则会对数据库恢复等方面带来不利的影响。

一个Oracle实例至少要有一个DBWR进程,初始化参数DB_WRITE_PROCESSES可以设置DBWR进程的个数。如果仅使用一个DBWR进程无法满足系统的需要,可以设置多个DBWR进程,则进程的名称分别为DBW0、DBW1、DBW2等。但是DBWR进程的数量不应当超过系统处理器的数量,否则多余的DBWR无法发挥作用,反而耗费系统资源。

2. LGWR(日志写进程)

日志写进程LGWR负责将重做日志缓冲区中的信息写入磁盘日志文件组。数据库在运行时,如果对数据进行了修改就会产生日志信息,日志信息首先保存在日志缓冲区中。当日志信息达到一定数量时,由LGWR将日志数据写入日志文件组。

由于日志缓冲区是一个循环缓冲区,因此在LGWR将日志缓冲区的日志数据写入日志文件组时,Oracle还能将新的日志信息写入日志缓存区。由于LGWR进程写入重做日志文件的速度要快于Oracle写入重做日志缓存的速度,因此能够保证重做日志缓存中始终有足够的空闲空间。

LGWR进程并不是随时都在运行,只有下述情况之一发生时,LGWR进程才开始将日志缓冲区中的数据写入日志文件组。

※ 用户提交当前事务。

※ 日志缓冲区被写满1/3。

※ DBWR进程将脏缓存块写入数据文件。

※ 每隔3s即发生一次超时,出现超时将启动LGWR。

如果日志文件组包含多个日志成员,则LGWR进程将日志信息同时写入一个日志文件组的多个日志成员文件中。如果组中一个成员文件已经损坏,LGWR进程可将日志信息继续写入该组的其他文件中,以免影响数据库的正常运行。

Oracle使用快速提交机制,即将事务提交首先写入日志文件组,但是其修改的数据可以还没有写入数据文件。如果事务的提交记录和重做信息都被写入重做日志文件,这样即使发生数据库崩溃,事务对数据库所做的更改也不会丢失,因为这可以通过相应的日志信息来恢复。

在LGWR执行日志切换时,它会生成一个检查点,而该检查点将通知DBWR将脏缓存块从缓存区写入数据文件中。这是很重要的,因为LGWR开始向另一个日志文件组写入日志时,可能需要覆盖另一个日志文件组中的日志信息,如果这些日志信息是一个事务留下的,而LGWR进程不在覆盖日志文件前通知DBWR将脏数据块写入数据文件,则这时如果数据库发生故障,将无法对其进行恢复。

3. CKPT(检查点进程)

“检查点”就是一个事件,当该事件发生时,数据缓存中的脏缓存块将被写入数据文件中,同时系统对数据库的控制文件和数据文件进行更新,以记录当前数据库的状态。在通常情况下,检查点是在日志切换时产生的。检查点可以保证所有被修改过的缓存块都被写入数据文件,此时数据库处于一个完整的状态。如果数据库崩溃,则只需要将数据库恢复到上一个检查点时刻即可,这样可以缩短数据库恢复所需的时间。

CKPT进程负责执行两个任务。

※ 检查点进程CKPT负责将检查点更新到控制文件。

※ 启动DBWR进程,将脏缓存块写入数据文件。

数据库管理员可以根据实际的情况为检查点选择一个合适的执行间隔。如果检查点执行间隔太短,将会产生过多的磁盘I/O操作;反之,如果检查点执行的间隔过长,则数据库恢复将耗费太多的时间。Oracle数据库提供了3个与检查点相关的初始化参数:一个是LOG_ CHECKPOINT_TIMEOUT参数,该参数决定执行一个检查点的时间间隔,这样每到一定的时间,无论数据库中是否有操作,都将产生检查点;另一个参数是LOG_CHECKPOINT_ INTERVAL,该参数决定执行一个检查点时需要填写的日志文件块数,即每产生多少个日志数据,系统产生一个检查点;LOG_ CHECKPOINT_TO_ALERT参数用于设置是否将检查点信息记录到警告日志中。通过将检查点信息记录到警告日志中,可以便于数据库管理员确定检查点是否按所需频率出现。

4. ARCn(归档进程)

Oracle数据库有两种运行模式:归档和非归档模式。如果数据库运行在非归档模式下,则日志文件在切换时将被直接覆盖,而不会产生归档日志,如下图所示。

当数据库运行在归档模式下时,如果发生日志切换,则启动归档进程ARCn,并将已写满的重做日志文件复制到指定的存储设备中,以避免已经写满的重做日志文件被覆盖,如下图所示。

如果要启动ARCn进程,则需要数据库运行在归档模式下。ARCn进程启动后,数据库将具有自动归档功能。在默认情况下,实例启动时只会启动一个归档进程ARC0。当ARC0进程在归档一个重做日志文件时,任何其他进程都无法访问这个重做日志文件。由于重做日志文件是循环使用的,如果LGWR进程要使用的下一个重做日志文件正在进行归档,数据库将被挂起,直到该重做日志文件归档完毕为止。因此,为了加快重做日志文件的归档速度,避免发生等待,LGWR进程会根据需要自动启动更多的归档进程。

5. SMON(系统监视进程)

系统监视进程SMON在数据库实例启动时负表对数据库进行恢复操作。如果数据库非正常关闭,则当下次启动数据库实例时,SMON进程将根据重做日志文件对数据库进行恢复。除此之外,SMON进程还负责回收临时表空间或临时段中不再使用的存储空间,以及合并各个表空间中空闲的空间碎片。

SMON进程除了会在数据库实例启动时执行一次外,在数据库实例运行期间,它会被定期唤醒,检查是否有工作需要它来完成。如果其他进程需要使用SMON进程的功能,则系统将随时启动SMON进程。

6. PMON(进程监视进程)

进程监视进程PMON主要用于清除失效的用户进程,释放用户进程所占用的资源。如PMON将回退未提交的工作,并释放分配给失败进程的SGA资源。

在某些情况下,用户与Oracle数据库的连接可能会非正常终止。例如,用户可能在没有从数据库中正常退出时就关闭了其客户端程序,或者由于网络突然中断而造成一个数据库连接非正常终止。在这些情况下,Oracle将启动PMON进程来启动清除中断或失败的用户进程,释放该进程所使用的系统资源。

除此之外,PMON进程还会周期性地检查调度程序和服务进程的状态,如果它们失败,PMON将尝试重新启用它们,并释放它们所占用的各种资源。与SMOP进程类似,PMON进程在数据库实例运行期间会被定期唤醒,以检查是否有工作需要它来完成。如果其他进程需要使用PMON进程完成某些任务,则PMON进程将会随时被启动。

7. RECO(恢复进程)

恢复进程RECO负责在分布式数据库环境中自动恢复那些失败的分布式事务。在分布式数据库系统中包含多个数据库实例,它们就像一个实例一样运行,其中任何一个实例都可以修改其他数据库中的数据。分布式数据库系统允许在多个数据库中进行数据修改,RECO进程负责查找分布在网络中的进程,帮助修复由于通信故障而失败的修改过程。RECO进程不断尝试所需的连接,使分布式系统更快地从通信故障中恢复过来。

8. Dnnn(调度进程)

当用户进程连接数据库实例后,需要一个服务进程为其提供服务,数据库为用户进程提供服务的方式称为“数据库操作模式”。Oracle数据库具有两种操作模式:专用服务器操作模式和共享服务器操作模式。

在专用服务器操作模式中,Oracle为每个连接数据库实例的用户进程启动一个专门的服务进程。专用服务器操作模式的结构如下图所示。

如上图所示,在专用服务器操作模式下,用户进程与服务器进程数的比例是1:1。这样,如果同一时刻有大量用户进程连接数据库,数据库实例必须创建相同数目的服务进程。当用户进程大部分时间为空闲时,数据库的效率比较低。因为在用户进程空闲期间,对应的服务器进程始终存在。因此,专用服务器操作模式一般应用于“在线事务处理(OLTP)”应用环境中,例如售票系统等。

与专用服务器操作模式不同,共享服务器操作模式可以实现只运行少量的服务器进程,由少量的服务进程为大量用户进程提供服务。在共享服务器操作模式下,在数据库实例启动同时也将启动一定数量的服务进程,在调度进程Dnnn的调度下为任意数量的用户进程提供服务。共享服务器操作模式的结构如下图所示。

由上图可以看出,调度进程Dnnn是位于用户进程与共享服务进程之间的关键进程,它负责将用户进程分配给空闲的服务进程,并将处理后的结果返回给用户进程。在一个数据库实例中,可以同时运行多个调度进程,每种网络协议至少要建立一个调用进程。数据库管理员可以根据实际的情况增加或删除调度进程。当启动多个调度进程时,各调度进程的名称依次为D000、D001、…、Dnnn。