Oracle数据库从入门到运维实战
上QQ阅读APP看书,第一时间看更新

1.3 实例中的后台进程

在一个大型数据库系统中,每时每刻都可能处理大量的用户请求,在数据库服务器中需要执行非常复杂的处理。例如,将脏缓冲区中的内容写入数据文件,将重做日志缓冲区中的重做日志写入重做日志文件,发出检查点以维护数据文件、控制文件和重做日志文件间的一致状态,在数据库服务器重新启动时进行实例恢复,进行重做日志归档等,这些任务都由实例中的后台进程来完成。

当实例启动时,这些后台进程将自动启动。每个进程都有特定的功能,同时,这些进程之间也会相互协作。例如,LGWR(日志写进程)用于把重做日志缓冲区中的重做日志写入重做日志文件,当重做日志文件被写满后,LGWR(日志写进程)将向ARCH(归档日志进程)发信号,由ARCH(归档日志进程)对重做日志文件进行归档。

需要注意的是,并不是所有的后台进程都需要启动。常用的后台进程及其功能如表1-1所示。

表1-1

实例启动后,可以查看正在运行的后台进程。例如,在SQL*Plus中查询动态性能视图V$BGPROCESS,可以获得正在运行的后台进程:

SQL>SELECT name FROM v$bgprocess WHERE paddr<>'00';  [0005]

其中,条件paddr<>'00'限定了“正在运行的后台进程”。

实例中的后台进程与SGA、数据文件、控制文件和重做日志文件的关系如图1-6所示。

图1-6

图1-6主要说明了Oracle的后台进程(Background Processes)的主要动作,具体如下。

DBWR(DBW0~n,数据库写进程)负责将内存数据写入DataFile(数据库物理数据文件)。

CKPT(检查点进程)负责检查Control File(控制文件)、DataFile(数据库物理数据文件)及Redo Log File(日志文件)。

LGWR(日志写进程)负责将内存数据写入Redolog(重做日志),在必要时通知ARCH(归档日志进程)进行归档操作。

ARCH(ARC0~n,归档日志进程)负责将Redolog(重做日志)归档到Archive Log(归档日志)。

在本节将主要介绍“DBWR(数据库写进程)”“LGWR(日志写进程)”“CKPT(检查点进程)”“SMON(系统监视进程)”“PMON(监控和管理进程)”及“ARCH(归档日志进程)”。

1.3.1 DBWR(数据库写进程)

DBWR(数据库写进程)的功能是将数据库高速缓存中的脏缓冲区内容写入数据文件中的数据块。当用户执行DML命令时,服务器进程在数据库高速缓存中的缓冲区中修改数据,并将修改后的缓冲区标志为“脏缓冲区”。DBWR(数据库写进程)将在一定的条件下将脏缓冲区的内容写入数据文件。

用户执行DML命令后,被修改的缓冲区并不是被立即写入数据文件,而是保留一段时间,即使用户执行了COMMIT操作。DBWR(数据库写进程)开始工作时,它将把一批脏缓冲区的内容一块写入数据文件。这样做的好处有两点:一是减少了写磁盘的次数,因为多次写磁盘的操作被合并为一次写操作;二是减少了读磁盘的次数,因为如果另一个用户正好也要对同样的数据进行处理,便可直接在脏缓冲区中进行。如果脏缓冲区被写入数据文件,它将成为空闲缓冲区,并且可能马上被其他的访问所使用。一旦空闲缓冲区被再次使用,那么当另一个用户要访问这个缓冲区中以前的内容时,只好重新从数据文件中读取。

用户访问数据库时,服务器进程如果发现需要的数据不在数据库高速缓存中,它将把数据从数据文件读到空闲缓冲区中,在此之前,服务器进程要在LRU队列中搜索合适数量的空闲缓冲区,在搜索过程中如果遇到一个脏缓冲区,服务器进程将把它记录在脏队列中,然后继续搜索。如果遇到忙缓冲区,将忽略它。DBWR(数据库写进程)工作时,将扫描脏队列,把那些位于脏队列中,并且最近很少被访问的脏缓冲区写入数据文件。而那些虽然位于脏队列,但最近仍被频繁访问的脏缓冲区,或者那些还没有被记录在脏队列中的脏缓冲区,仍然可以保持“脏”状态,直到被写入数据文件。

在一个实例中,可以启动多个DBWR(数据库写进程),在默认情况下只启动一个。如果用户的事务很频繁,那么在数据高速缓存中将瞬间产生大量的脏缓冲区,对于一个DBWR(数据库写进程)来说,要把这些脏缓冲区写入数据文件,负载是很重的。这时可以考虑启动额外的DBWR(数据库写进程),以提高写数据的效率。DBWR(数据库写进程)的数目由初始化参数DB_WRITER_PROCESSES指定,最多可以启动20个(DBW0~DBW9以及DBWa~DBWj)。

DBWR(数据库写进程)并不是越多越好,一个基本的原则是,这个进程的数目不要超过CPU的数目,如果计算机中只有一个CPU,多个DBWR(数据库写进程)在CPU中只能以串行方式运行。而且计算机中如果只有一个硬盘,对数据库的写操作也只能以串行方式进行,如果多个DBWR(数据库写进程)同时写数据文件,将发生磁盘访问冲突。

DBWR(数据库写进程)在以下几种情况执行写操作:

●固定的时间间隔(如每隔3秒);

●当数据库服务器发出检查点时;

●当脏队列中的缓冲区数目达到一定值时,也就是说,在数据库高速缓存中不能有太多的脏缓冲区;

●当用户执行了某操作,需要在数据库高速缓存中搜索一定数量的空闲缓冲区时,空闲缓冲区的数量不能满足要求,这时DBWR(数据库写进程)将把脏队列中的一部分脏缓冲区写入数据文件,这部分脏缓冲区将重新成为空闲缓冲区。

1.3.2 LGWR(日志写进程)

LGWR(日志写进程)的功能是将重做日志缓冲区中的重做日志写入重做日志文件,这是Oracle确保数据库一致性的一种重要手段。

当用户执行DML或DDL语句时,服务器进程首先在重做日志缓冲区中生成重做日志,然后才修改数据库高速缓存中相应的缓冲区。在一定的条件下,LGWR(日志写进程)将重做日志缓冲区中的重做日志写入重做日志文件,而DBWR(数据库写进程)也将在一定的条件下,把数据库高速缓存中的脏缓冲区写入数据文件,这两个进程并不是同步的。

LGWR(写日志进程)被启动执行的时机有以下几种情况:

●固定的时间间隔(如每隔3秒);

●用户执行了COMMIT操作;

●重做日志缓冲区已经有1/3的空间被写满;

●DBWR(数据库写进程)将脏缓冲区写入数据文件之前。

由此可见,如果脏缓冲区中的数据被写入数据文件,那么重做日志一定被写入重做日志文件。而用户数据还没有被写入数据文件时,重做日志也可能被写入重做日志文件,也可能没有。

SGA中的重做日志缓冲区是一段可循环使用的存储区域。一方面,服务器进程将生成的重做日志写入重做日志缓冲区,占用一部分空间。另一方面,LGWR(日志写进程)将重做日志写入重做日志文件,释放一部分空间。由于LGWR(日志写进程)将重做日志写入重做日志文件的速度高于服务器生成重做日志的速度,所以在任何情况下重做日志缓冲区中始终都有足够的空闲空间。重做日志缓冲区的使用情况如图1-7所示。

图1-7

当用户执行事务时,服务器进程一方面在重做日志缓冲区中产生重做日志;另一方面,在数据高速缓存中修改数据。对重做日志缓冲区和重做日志文件是按顺序写的,效率很高,而对数据高速缓存和数据文件都是随机写的,因为数据的分布并没有什么规律,所以效率较低。如果写日志和写数据是同步进行的,那么整个数据库的性能就不可能很高。

为了提高处理事务的效率,Oracle采取了“快速提交”的机制。当用户执行一个事务时,这个事务将获得一个SCN,同时产生重做日志,重做日志被写入重做日志缓冲区。在此之后,服务器进程才在数据高速缓存中修改数据。如果用户提交了事务,SCN也将被写入重做日志缓冲区,然后LGWR(日志写进程)立即开始工作,将这个事务的重做日志和SCN一起写入重做日志文件,这个事务就算成功地执行结束了。而与这个事务有关的脏缓冲区这时并没有写入数据文件,而是由DBWR(数据库写进程)在适当的时候写入。

在这里向大家介绍一个概念,即SCN(System Change Number,系统改变号)。SCN是用于记录数据库变化的一个数字,它是一个正整数。当一个事务执行之后,便获得一个新的SCN,每个SCN在整个数据库中都是唯一的,而且所有SCN的值是递增的,随着数据库的运行,SCN不断增大,并且永远不会重复,也没有消耗完的时候。SCN被同时记录在数据文件、控制文件和重做日志文件中,如果这3个文件的SCN完全一致,数据库就达到了一个完全一致的状态。

现在考虑一个非常复杂的问题,Oracle如何利用重做日志确保数据库的一致性?如果发生了系统断电,用户执行的事务是否有效?Oracle如何利用重做日志进行数据库的恢复?

假设用户执行了一条DML命令,如UPDATE。假设在执行这条命令之前数据库的SCN值为2000,在执行这条DML命令之后,这个事务获得的SCN是2010。现在来分析两种常见的情况。

(1)用户没有提交事务的情况

根据DBWR(数据库写进程)、LGWR(日志写进程)的工作时机可知,这次事务带来的变化可能已经被写入数据文件和重做日志文件,也可能没有。但是无论是否写入,这次事务都是无效的,因为新的SCN没有被写入数据文件、控制文件和重做日志文件,这3种文件中记录的还是原来的SCN值,即2000。如果此刻系统突然断电,那么数据库服务器在重新启动时,将检查这3种文件中记录的SCN,并且回退最后一个SCN之后的所有事务。也就是说,用户执行了一条DML命令,但是因为没有提交该事务,系统发生断电等故障时,数据将丢失,无法恢复。

(2)事务被提交的情况

当用户执行COMMIT命令提交事务时,重做日志缓冲区中的重做日志和新的SCN将被写入重做日志文件。尽管这个事务所产生的脏缓冲区可能还没有被DBWR(数据库写进程)写入数据文件,但这个事务已经有效。考虑上面提到的UPDATE命令,这时重做日志文件记录的是新的SCN值,即2010,但是这个SCN值还没有被写入数据文件和控制文件。如果这3个文件的SCN不一致,那么重做日志文件中记录的SCN一定大于数据文件和控制文件中的SCN。如果此刻系统突然断电,那么数据库服务器在重新启动时,将检查这3种文件中记录的SCN,并且重新执行两个SCN之间的所有事务,然后将其中未提交的事务回滚,这样3种文件中的SCN将达到一致,然后才打开数据库,这时数据库达到了一致的状态。数据库的这种操作称为“实例恢复”,实例恢复是根据重做日志文件的内容进行的,这个过程由后台进程SMON(系统监视进程)完成。SMON(系统监视进程)将重做日志文件中记录的事务重新执行一次,从而确保了数据不会因为系统故障而丢失。

那么在系统运行过程中,3种文件中的SCN能不能达到一致呢?答案是肯定的,这要依赖于后台进程CKPT(检查点进程)。当CKPT(检查点进程)开始工作时,SCN将被写入数据文件和控制文件,使3种文件的SCN完全一致。同时CKPT(检查点进程)通知DBWR(数据库写进程)开始工作,把脏缓冲区中的数据写入数据文件。这时数据库将达到完全一致的状态,系统断电时数据库将不受任何影响,也不需要进行实例恢复。

由此可见,只有当事务被提交后,才有可能进行实例恢复,用户的数据才不至于丢失。如果事务没有提交,数据是无法进行恢复的。

1.3.3 CKPT(检查点进程)

CKPT(检查点进程)的功能是发出检查点。检查点是一种数据库事件,当数据库服务器发出检査点时,SCN将被写入数据文件和控制文件,而且数据库高速缓存中的脏缓冲区将被DBWR(数据库写进程)写入数据文件,这时数据库达到完全一致的状态。

数据库服务器是依靠SCN来维护数据文件、控制文件和重做日志文件之间的一致状态的。如果一个事务没有提交,脏缓冲区及重做日志缓冲区中的内容可能已经被写入数据文件和重做日志文件。这时如果数据库服务器发出检查点,3种文件的SCN达到一致,数据库达到一种一致状态。但这3种文件中记录的是该事务之前的SCN。数据库服务器如果重新启动,这个事务将被回滚,因为它处于最后一个SCN之后。

如果事务被提交,新的SCN将首先被写入重做日志文件,这时数据库服务器如果发出检查点,新的SCN被写入数据文件和控制文件,3种文件的SCN完全相同,数据库达到一致状态。在这种情况下,数据库服务器在重新启动时就不需要进行实例恢复。相反,如果没有发出检查点,那么在数据文件和控制文件中保持原来的SCN。如果系统断电,数据库服务器在重新启动时,将进行实例恢复,两个SCN之间的所有事务将被重新执行一次,使数据库达到一致状态。

CKPT(检查点进程)的任务有两个:一是通知DBWR(数据库写进程),将数据库高速缓存中所有脏缓冲区写入数据文件;二是发出检查点,将SCN的值写入数据文件和控制文件的头部。可见,当数据库服务器发出检查点时,将带来大量的磁盘I/O,因此,应尽量减少检查点的发生。

CKPT(检查点进程)在以下几种情况下被启动执行:

(1)正常关闭数据库服务器时;

(2)进行日志切换时;

(3)手工发出检查点(执行ALTER SYSTEM CHECKPOINT命令);

(4)由初始化参数LOG_CHECKPOINT_TIMEOUT和LOG_CHECKPOINT_NTERVAL指定的时机来到时。

与检查点的发生时机有关的两个初始化参数为:

●LOG_CHECKPOINT_TIMEOUT:用于指定两个检查点之间的时间间隔(以秒为单位)。Oracle 11g中这个参数的默认值为1800,即30分钟。如果设置为0,将取消固定时间间隔方式的检查点;

●LOG_CHECKPOINT_NTERVAL:该参数指定了一个操作系统块的数目,可以看作是检查点在空间上发生的间隔。当往重做日志缓冲区中写入指定块数的重做日志时,将发出检査点。

在管理数据库时,应为检查点设置合理的时间、空间间隔。如果间隔太大,对数据文件的写操作次数将减少,数据文件与重做日志文件的SCN将相差较大,在系统断电时,进行实例恢复的时间将加长。反之,如果间隔太小,磁盘写操作将被频繁执行,数据库的性能将降低。但这样做的好处是,在系统断电时实例恢复的时间将被缩短。

现在以一个不合理的检查点间隔的例子来说明如何消除不必要的检查点。假设操作系统块的大小为1024字节,初始化参数LOG_CHECKPOINT_INTERVAL的值为4608,重做日志文件的大小为10MB。那么每当向重做日志文件中写入1024×4608=4.5MB的重做日志时,数据库服务器将发出检查点。这样在两个检查点之后,重做日志文件将被写满9MB。如果再写入1MB,就会进行日志切换,并自动发出一个检查点。这样最后两个检查点的间隔仅为1MB,显然间隔太短。所以在设置LOG_CHECKPOINT_INTERVAL参数时要考虑重做日志文件的大小,尽量将一些检查点与切换日志时发出的检查点合并。

1.3.4 SMON(系统监视进程)

SMON(系统监视进程)的功能是监视数据库服务器的运行状况,并执行一些必要的清理工作。在数据库服务器启动时,SMON(系统监视进程)将检查数据文件、控制文件和重做日志文件,并根据这3个文件的SCN值进行实例恢复,或者回滚未提交的事务。

另外,SMON(系统监视进程)还可以对数据库的存储空间进行一些常规的管理。具体的功能如下:

●回收临时表空间中不再使用的临时段;

●在字典管理表空间中合并相邻的空闲存储空间。

在数据库服务器重新启动时,SMON(系统监视进程)负责进行实例恢复,并对数据库的存储空间进行管理。在实例正常运行时,SMON(系统监视进程)也会经常工作,或者被其他进程调用,这时它的功能仅限于对存储空间进行管理。

1.3.5 PMON(监控和管理进程)

PMON(监控和管理进程)的功能是定期检查用户进程,并进行回收资源的操作。

当用户访问数据库时,用户进程与服务器进程建立连接。当用户进程断开连接时,PMON(监控和管理进程)负责回收为其服务的服务器进程所占用的资源。

如果由于某种原因使连接非正常断开,如用户进程异常终止,或网络发生故障,用户进程所占用的资源还没有释放。PMON(监控和管理进程)负责检查所有用户进程的状态,清除非正常终止的用户进程,并回收它们所占用的资源,如锁、存储区域等,终止相应的子进程,并释放对应服务器进程所占用的资源。

PMON(监控和管理进程)还有一个功能,就是将实例和调度器注册到网络监听器中。当实例启动时,PMON(监控和管理进程)负责将实例的信息注册到监听器中。如果监听器没有启动,PMON(监控和管理进程)将周期性地察看它的状态。

1.3.6 ARCH(归档日志进程)

ARCH(归档日志进程)的功能是对重做日志文件进行归档。

数据库的重做日志记录在重做日志文件中。在一个数据库中往往需要若干组重做日志文件,这些文件是循环使用的。当一组重做日志文件被写满时,数据库服务器自动进行日志切换,重做日志接着被写入下一组重做日志文件。当数据库服务器再一次使用一组重做日志文件时,文件中以前的内容将被覆盖,而且永远无法恢复。

随着数据库服务器的运行,重做日志文件不断被覆盖。可以想象,如果系统发生故障,造成数据丢失,这时要对数据进行恢复。数据恢复需要用到对数据库所进行的备份,以及重做日志。如果重做日志缺失,那么最后一段时间的数据将无法恢复。为了防止这种情况的发生,Oracle提供了一种归档日志模式。在这种模式下,数据库服务器将自动对重做日志文件进行归档。如果数据库处于归档日志模式下,ARCH(归档日志进程)将自动启动,当一个重做日志文件被写满时,要进行日志切换,ARCH(归档日志进程)将对刚刚写满的重做日志文件进行归档,将重做日志文件的内容保存在归档日志文件中。

有了归档日志文件,数据库管理员再也不用担心重做日志文件被覆盖的事情发生了。由于日志归档是自动进行的,所以数据库服务器可以顺利地进行日志切换,无须人工干预。

如果数据库处于非归档日志模式下,重做日志文件是不会被归档的。只有数据库处于归档日志模式下,并且启动了ARCH(归档日志进程),数据库服务器才会自动对重做日志进行归档。在一个实例中可以启动多个ARCH(归档日志进程),默认情况只启动4个。

与ARCH(归档日志进程)有关的初始化参数如表1-2所示。

表1-2

如果数据库服务器写重做日志文件的速度比日志归档的速度要快,那么将发生数据库服务器被阻塞的现象。所以在服务器写重做日志的操作非常频繁的情况下,可以启动多个ARCH(归档日志进程),以加快日志归档的速度。