Oracle从入门到精通(第5版)
上QQ阅读APP看书,第一时间看更新

2.4 Oracle服务器结构

Oracle服务器主要由实例、数据库、程序全局区(PGA)和前台进程组成,如图2.15所示。

实例可以进一步划分为系统全局区(SGA)和后台进程(PMON、SMON等)两部分。其中,SGA使用操作系统的共享内存资源,而后台进程需要使用CPU与共享内存资源。数据库(database)中包含数据文件(data file)、控制文件(control file)和重做日志文件(redo log file),这些数据库文件存储在硬盘中。PGA是一个非共享的内存区域,用于管理用户进程的私有资源。前台进程可以再划分为用户进程和服务器进程,它们需要使用CPU与内存资源。

2.3节已经对数据库的3种物理文件进行过详细讲解,本节主要对实例、程序全局区和前台进程进行详细的讲解。

图2.15 Oracle服务器结构模型

2.4.1 系统全局区

系统全局区(system global area,SGA)是所有用户进程共享的一块内存区域,也就是说,SGA中的数据资源可以被多个用户进程共同使用。SGA主要由高速数据缓冲区、重做日志缓冲区、共享池、大型池和Java池等内存结构组成。SGA随着数据库实例的启动被加载到内存中,当数据库实例关闭时,SGA区域将会随之消失。

1.高速数据缓冲区

高速数据缓冲区中存储着Oracle系统最近访问过的数据块(数据块在高速缓冲区中也可称为缓存块)。当用户向数据库发出请求时(如检索某一条数据),如果在高速数据缓冲区中存在请求的数据,则Oracle系统会直接从高速数据缓冲区中读取数据并返回给用户;否则,Oracle系统会打开数据文件读取请求的数据。

若无法在高速数据缓冲区中找到所需要的数据,则Oracle首先从数据文件中读取指定的数据块到高速数据缓冲区中,然后再从高速数据缓冲区中将请求的数据返回给用户。由于高速数据缓冲区被所有的用户所共享,只要数据文件中的某些数据块被当前用户或其他用户请求过,这些数据块就会被装载到高速数据缓冲区中。这样当任何用户再次访问相同的数据时,Oracle就不必再从数据文件中读取数据,而是可以直接将高速数据缓冲区中的数据返回给用户。经常或最近被访问的数据块会被放置到高速数据缓冲区的前端,不常被访问的数据块会被放置到高速数据缓冲区的后端,当高速数据缓冲区被填满时,会自动挤掉一些不常被访问的数据块。

以存取速度来看,内存的读取速度远快于物理硬盘,所以高速数据缓冲区的存在可大大降低对物理磁盘的读取频率,从而达到提高数据库服务器性能的目的。为了便于管理SGA的内存数据,Oracle把高速数据缓冲区分为以下3个部分。

 脏数据区。脏数据区中存储着已被修改过的数据,这些数据等待被写入数据文件中。当一条更新或删除语句对某些数据块中的数据修改后,那么这些数据块就被标记为“脏”,然后等待提交命令并通过后台进程DBWR将其写入数据文件中。

 空闲区。空闲区中的数据块不包含任何数据,这些数据块可以被写入数据,Oracle可以从数据文件中读取数据块,并将其存储到该区中。

 保留区。保留区包含那些正在被用户访问的数据块和明确保留以作为将来使用的数据块(即缓存块),这些数据块将被保留在缓冲区中。

2.重做日志缓冲区

重做日志缓冲区用于存储对数据库进行修改操作时所产生的日志信息,这些日志信息在写入重做日志文件中之前,首先存储到重做日志缓冲区中,然后当检查点发生或重做日志缓冲区中的信息量到达一定峰值时,由日志写入(LGWR)进程将此缓冲区的内容写入重做日志文件中。

重做日志缓冲区的大小由log_buffer参数指定,该参数也可以在实例启动后动态修改。相对于高速数据缓冲区而言,重做日志缓冲区的大小对数据库性能的影响较小,通常较大的重做日志缓冲区能减少重做日志文件对I/O的读写次数,对数据库的整体性能有一定的提高。

3.共享池

共享池是SGA保留的内存区域,用于缓存SQL语句、PL/SQL语句、数据字典、资源锁、字符集以及其他控制结构等。共享池包含库高速缓冲区(library cache)和字典高速缓冲区(dictionary cache)。

1)库高速缓冲区

库高速缓冲区是共享池的一部分,主要包括共享SQL区和私有SQL区两个组成部分。库高速缓冲区中存储最近用过的SQL语句、PL/SQL语句的文本和执行计划。当下一次执行相同的SQL语句或PL/SQL语句时,可以直接在库高速缓冲区中找到之前已生成的执行计划,而不需要再次解析相同的SQL语句或PL/SQL语句,从而提高系统执行效率。

每条被缓存的SQL或PL/SQL语句都被分成两部分,分别被存储在共享SQL区和私有SQL区中。共享SQL区存储SQL或PL/SQL语句的语法分析结果和执行计划,如果以后要再次执行类似的语句,可以利用共享SQL区中已缓存的语法分析结果和执行计划;私有SQL区存储SQL语句中的绑定变量、环境和会话等信息,这些信息属于执行该语句的用户的私有信息,其他用户则无法共享这些信息。

2)字典高速缓冲区

字典高速缓冲区用于存储Oracle系统内部管理所需要的数据字典信息,如用户名、数据对象和权限等。

共享池的内存空间大小是可以被动态改变的,一般通过修改参数SHARED_POOL_SIZE的值来实现。

【例2.16】修改Oracle共享池的内存空间大小为30 MB,代码及其运行结果如下。

     SQL> alter system set shared_pool_size=30m;
     系统已更改。

注意

Oracle共享池的空间并非越大越好,因为系统的内存资源是有限的,而且操作系统本身也要消耗一定的内存空间。

互动练习:改变数据库高速缓冲区的大小。

4.大型池

大型池在SGA区中不是必需的内存结构,只有在某些特殊情况下,实例才需要使用大型池来减轻共享池的访问压力,常用的情况有以下几种。

 当使用恢复管理器进行备份和恢复操作时,大型池将作为I/O缓冲区使用。

 当使用I/O Slave仿真异步I/O功能时,大型池将被当作I/O缓冲区使用。

 执行具有大量排序操作的SQL语句。

 当使用并行查询时,大型池将作为并行查询进程彼此交换信息的地方。

大型池的缓存区大小是通过LARGE_POOL_SIZE参数定义的,在Oracle中,用户可以使用ALTER SYSTEM命令动态地修改其缓存区的大小。

【例2.17】修改Oracle大型池的缓存区大小为16 MB,代码及其运行结果如下。

     SQL> alter system set large_pool_size = 16m;
     系统已更改。
     SQL> show parameter large_pool_size;
     NAME                                 TYPE        VALUE
     --------------------                ---------  ------------------------------
     large_pool_size                         big integer    16M

注意

如果在SGA区没有设置大型池,则在实例需要时,Oracle系统会在共享池或PGA中分配一定的缓存空间,这样势必会影响共享池或PGA的工作效率。

5.Java池

Java池用来提供内存空间给Java虚拟机使用,目的是支持在数据库中运行Java程序包,其大小由java_pool_size参数决定。

6.Oracle流池

Oracle流池用于在数据库与数据库之间进行信息共享。如果没有用到Oracle流,就不需要设置该池。Oracle流池的大小由参数streams_pool_size决定。

2.4.2 程序全局区

程序全局区(program global area,PGA)又称作用户进程全局区,它的内存区在进程私有区中,而不是在共享区中。PGA是一个全局区,可以把代码、全局变量和数据结构都存储在其中,但区域内的资源并不像SGA一样可被所有的用户进程所共享,而是每个Oracle服务器进程都只拥有属于自己的那部分PGA资源。

在程序全局区中,一个服务进程只能访问属于它自己的那部分PGA资源区,各个服务进程的PGA的总和即为实例的PGA的大小。通常PGA由私有SQL区和会话区组成。

1.私有SQL区

私有SQL区用于存储变量以及SQL语句运行时的内存结构信息,每个用户连接到实例时,都会在实例中创建一个会话。这些会话可能会在SGA区中创建一个共享SQL区,但在PGA区中可能会创建多个私有SQL区。把一个私有SQL区与对应的共享SQL区合并在一起,就可以获得一条SQL语句的完整缓存数据。

另外,每个会话的私有SQL区都可以再分为静态区和动态区两部分。静态区的信息在会话过程中保持不变,只有当会话结束时,静态区才会被释放;而动态区的信息在整个会话过程中是不断变化的,一旦SQL语句执行完毕,即使会话还没有结束,动态区也会被释放。

2.会话区

会话区用于存储用户的会话信息(如登录用户名)。如果数据库处于共享服务器连接模式下,则会话区将位于SGA中,而不是PGA中,用户特别需要注意这一点。

查看程序全局区的信息可以通过显示PGA参数的内容来实现。

【例2.18】显示当前用户进程的PGA信息,代码及其运行结果如下。

     SQL> show parameter pga;
     NAME                                 TYPE        VALUE
     ---------------------               ---------  ------------------------------
     pga_aggregate_target                   big integer    18M

2.4.3 前台进程

前台进程包括用户进程和服务器进程,它不属于实例的一部分,但是用户在不知不觉中经常会用到它。使用前台进程能够实现用户与实例的沟通,下面对这两种前台进程进行讲解。

1.用户进程

用户进程是指那些能够产生或执行SQL语句的应用程序,无论是SQL*Plus,还是其他应用程序,只要是能生成或执行SQL语句,都被称作用户进程。

在用户进程中有两个非常重要的概念,即连接和会话。连接是一个用户进程与实例之间建立的通信渠道,这个渠道可以通过操作系统上的相关通信机制或网络连接来实现;会话是指在用户进程与实例之间建立连接后形成的用户与实例之间的交互方式,一般是用户发出请求,数据库实例为用户返回响应消息的方式。例如,用户在SQL*Plus中发出connect system/1qaz2wsx的请求命令,若用户名和密码都正确,则数据库实例将返回“已连接”的响应消息。

2.服务器进程

服务器进程是用于处理用户会话过程中向数据库实例发出的SQL语句或SQL*Plus命令,它可以分为专用服务器模式和共享服务器模式。在专用服务器模式下,每个用户进程都有一个专用的服务器进程,这个服务器进程代表用户进程执行SQL语句,必要时还可以回传执行结果给用户进程;在共享服务器模式下,每个用户进程不直接与服务器进程连接,而是连接到分派程序,每个分派程序可以同时连接多个用户进程。

2.4.4 后台进程

Oracle后台进程是一组运行于Oracle服务器端的后台程序,是Oracle实例的重要组成部分。这组后台进程有若干个,如图2.16所示。其中SMON、PMON、DBWR、LGWR和CKPT这5个后台进程必须正常启动,否则将导致数据库实例崩溃。此外,还有很多辅助进程,用于实现相关的辅助功能,如果这些辅助进程发生问题,仅使某些功能受到影响,一般不会导致数据库实例崩溃。下面对其中的主要进程进行讲解。

图2.16 主要后台进程

1.数据写入进程

数据写入(DBWR)进程的主要任务是将内存中的“脏”数据块回写到数据文件中。所谓的“脏”数据块是指高速数据缓冲区中被修改过的数据块,这些数据块的内容与数据文件的数据块内容不一致。但DBWR并不是随时将所有的“脏”数据块都写入数据文件中,只有满足一定的条件时,DBWR进程才开始成批量地将“脏”数据块写入数据文件中,Oracle这样做的目的是尽量减少I/O操作,提高Oracle服务器性能。通常当发生以下几种情况时,DBWR进程会将“脏”数据块写入数据文件中。

 当用户进程执行插入或修改等操作时,需要将“新数据”写入高速数据缓冲区中,如果在高速数据缓冲区中没有找到空闲数据块来存储这些“新数据”,那么Oracle系统将启动DBWR进程并将“脏”数据块写入数据文件中,以获得空闲数据块来存储这些“新数据”。

 检查点进程启动后,它会强制要求DBWR将某些“脏”数据块写入数据文件中。

 当“脏”数据块在高速数据缓冲区中存储超过3 s时,DBWR进程将会自行启动并将某些“脏”数据块写入数据文件中。

在某些比较繁忙的应用系统中,可以修改服务器参数文件SPFILE的DB_WRITER_PROCESSES参数,以允许使用多个DBWR进程。但是DBWR进程的数量不应当超过系统处理器的数量,否则多余的DBWR不但无法发挥作用,反而会耗费系统资源。

2.检查点进程

检查点(CKPT)进程可以被看作一个事件,当检查点事件发生时,CKPT会要求DBWR将某些“脏”数据块回写到数据文件中。当用户进程发出数据请求时,Oracle系统从数据文件中读取需要的数据并存储到高速数据缓冲区中,用户对数据的操作是在缓冲区中进行的。当用户操作数据时,就会产生大量的日志信息并存储在重做日志缓冲区,当Oracle系统满足一定条件时,日志写入(LGWR)进程会将日志信息写入重做日志文件组中,当发生日志切换时(写入操作正要从一个日志文件组切换到另一组时),就会启动检查点进程。

另外,数据库管理员(DBA)还可以通过修改初始化参数文件SPFILE中的CHECKPOINT_PROCESS参数为TRUE来启动检查点进程。

3.日志写入进程

日志写入(LGWR)进程用于将重做日志缓冲区中的数据写入日志文件中。Oracle系统首先将用户所做的修改日志信息写入日志文件中,然后再将修改结果写入数据文件中。

Oracle实例在运行中会产生大量日志信息,这些日志信息首先被记录在SGA的重做日志缓冲区中,当发生提交命令,或者重做日志缓冲区的信息满1/3,或者日志信息存储超过3 s时,LGWR进程就将日志信息从重做日志缓冲区中读出并将其写入日志文件组中序号较小的文件中,在一个日志文件组中被写满后接着写入另外一组中。当LGWR进程将所有的日志文件都写过一遍之后,它将再次转向第一个日志文件组重新覆盖,如图2.17所示。当LGWR进程写满一个日志文件组而转向写另外一组时,称之为日志切换。

4.归档进程

归档(ARCH)进程是一个可选择的进程,只有当Oracle数据库处于归档模式时,该进程才可能起到作用。若Oracle数据库处于归档模式,当各个日志文件组都被写满,在即将被覆盖之前,先由ARCH把即将被覆盖的日志文件中的日志信息读出,然后再把这些“读出的日志信息”写入归档日志文件中,如图2.18所示。

图2.17 通过LGWR写日志文件

图2.18 通过ARCH写归档文件

当系统比较繁忙而导致LGWR进程处于等待ARCH进程时,可通过修改LOG_ARCHIVE_MAX_PROCESSES参数启动多个归档进程,进而提高归档写磁盘的速度。

5.系统监控进程

系统监控(SMON)进程是在数据库系统启动时执行回复工作的强制性进程。例如,在并行服务器模式下,SMON可以回复另一条处于失败的数据库,使系统切换到另一台正常的服务器上。

6.进程监控进程

进程监控(PMON)进程用于监控其他进程的状态,当有进程启动失败时,PMON会清除失败的用户进程,释放用户进程所用的资源。

7.锁进程

锁(LCKN)进程是一个可选进程,在并行服务器模式下可以出现多个锁定进程以利于数据库通信。

8.恢复进程

恢复(RECO)进程是在分布式数据库模式下使用的一个可选进程,用于数据不一致时的恢复工作。

9.调度进程

调度(DNNN)进程是一个可选进程,在共享服务器模式下使用,可以启动多个调度进程。

10.快照进程

快照(SNPN)进程用于处理数据库快照的自动刷新,并通过DBMS_JOB包运行预定的数据库存储过程。

以上讲解了Oracle中的若干个典型进程。Oracle的版本不同,其后台进程也不同,默认情况下Oracle会启动200多个后台进程。

【例2.19】从v$bgprocess数据字典中查询当前实例的进程信息,代码如下。(实例位置:资源包\TM\sl\2\9)

     SQL> set pagesize 50;
     SQL> select name,description from v$bgprocess;

本例运行结果如图2.19所示。

图2.19 当前实例进程信息

互动练习:回顾Oracle执行SQL查询语句的步骤。