Oracle 内存体系结构详解

1、Oracle服务器

由Oracle实例和Oracle数据库两大部分组成。

1.1、Oracle实例

是一种数据库访问机制,主要由内存结构和进程结构组成。

内存结构主要包括系统全局区(System Global Area,SGA)、进程全局区(Process Global Area,PGA)等

实例的后台进程有5个是必须的

SMON 系统监视器进程

PMON 进程监视器进程

DBWR 数据库书写器

LGWR 日志书写器

CKPT 检查点进程

每个实例只能操作其对应的一个数据库,但一个数据库可以同时被几个实例操作(RAC)

1.2 Oracle数据库

由以下三种操作系统文件组成:

控制文件(control files)

数据文件(data files)

重做日志文件(redo log files)

其它服务器文件:

初始化参数文件(parameter files)

口令文件(password files)

归档重做日志文件(archived redo log files)

3、与Oracle服务器的连接

一个连接即称为一个会话,连接可分为以下两种:

  • 1、专用服务器连接

一个用户进程对应创建一个服务器进程,用户进程与服务器进程是一对一的关系。

  • 2、共享服务器连接

多个用户进程同时对应一个服务器进程。

各种不同的连接方式

  • 1、基于主机方式

用户进程与服务器进程运行在同一台计算机相同的操作系统下,用户进程与Oracle服务器的通信是通过操作系统内部的进程通信(inter process communication,IPC)机制来建立的。

  • 2、客户端-服务器(client-server)(两层模型)方式

用户进程与Oracle服务器的通信是通过网络协议(如TCP/IP)来完成的。

  • 3、客户端-应用服务器-服务器(client-application server-server)(三层模型)方式

用户的个人计算机通过网络与应用服务器或网络服务器进行通信,该应用服务器或网络服务器同样再通过网络与运行数据库的计算机连接。

4、Oracle执行SQL查询语句的步骤

  • 1、SQL正文放入共享池(shared pool)的库缓存(library cache)。

  • 2、检查是否有相同的SQL正文,没有就进行以下编译处理,否则跳过。

    • 1)语法检查
    • 2)通过数据字典检查表和列的定义
    • 3)对所操作的对象加编译锁,防止编译期间的对象定义被改变
    • 4)检查用户权限
    • 5)生成执行计划
    • 6)将编译后的代码和执行计划放入共享SQL区
  • 3、执行

由服务器进程执行SQL语句。

  • 4、提取数据

由服务器进程选择所需的数据行,需要时排序(PGA中),返回给用户进程。

5、系统全局区(System Global Area,SGA)

SGA包含以下几大块:

固定区域(Fixed Size):存储SGA中各个组件的信息,大小不能修改

可变区域(Variable Size):包括共享池、大池、流池、JAVA池

数据库高速缓冲区缓存(Database buffer cache):大小由参数db_cache_size指定(10g后参数db_cache_size默认为0)

重做日志缓冲区缓存(Redo log buffer cache):大小通常大于参数log_buffer的设置,因为在内存中还要设置保护页对log buffer进行保护。

以下命令可以看到SGA的内存分配概览

show sga
Total System Global Area 4960579584 bytes
Fixed Size                  2184232 bytes
Variable Size            2902461400 bytes
Database Buffers         2046820352 bytes
Redo Buffers                9113600 bytes

或者

select * from v$sga;
NAME                      VALUE
------------------- ----------
Fixed Size              2184232
Variable Size        2902461400
Database Buffers     2046820352
Redo Buffers            9113600

5.1共享池(shared pool)

用于存放SQL语句、PL/SQL代码、数据字典、资源锁和其他控制信息。它由初始化参数SHARED_POOL_SIZE控制其大小。它包含以下几个缓冲区:

  • 1、数据字典缓存(data dictionary cache):用于存储经常使用的数据字典信息。比如(表的定义、用户名、口令、权限、数据库的结构等)。Oracle运行过程中经常访问该缓存以便解析SQL语句,确定操作的对象是否存在,是否具有权限等。如果不在数据字典缓存中,服务器进程就从保存数据字典信息的数据文件中将其读入到数据字典缓存中。数据字典缓存中保存的是一条一条的记录(就像是内存中的数据库),而其他缓存区中保存的是数据块信息。
  • 2、库缓存(Library Cache):用于保存最近解析过的SQL语句、PL/SQL过程。Oracle在执行一条SQL语句、一段PL/SQL过程前首先在库缓存中搜索,如果查到它们已经解析过了,就利用库缓存中的解析结果和执行计划来执行,而不必重新对它们进行解析,显著提高执行速度。Oracle是通过比较SQL或PL/SQL语句的正文来决定两个语句是否相同的,只有正文完全相同,Oracle才重用已存在的编译后的代码和执行计划。应该尽量用绑定变量的方式写SQL,绑定变量不是在编译阶段赋值的,而是在运行阶段赋值的,因此语句可以不用重新编译。

库缓存的管理采用LRU(least recently used)的队列算法,即最近最少使用的队列算法。刚使用的内存块放在LRU队列的头部,而进程每次从队列的尾部获取内存块,获取到的内存块立即移至队列头部。最终使长时间没有使用到的内存块自然移到了队列的尾部而被最先使用。

Oracle没有提供单独设置库缓存或数据字典缓存空间大小的方法,而是通过设置共享池的大小来间接设置,通过参数SHARED_POOL_SIZE可调整,其大小受限于SGA的尺寸SGA_MAX_SIZE参数。

ORACLE将每一条SQL语句分解为可共享、不可共享的两部分。

共享SQL区:存储的是最近执行的SQL语句、解析后的语法树和优化后的执行计划。这样以后执行相同的SQL语句就直接利用在共享SQL区中的缓存信息,不必重复语法解析了。Oracle在执行一条新的SQL语句时,会为它在共享SQL区中分配空间,分配的大小取决于SQL语句的复杂度。如果共享SQL区中没有空闲空间,就利用LRU算法,释放被占用的空间。

私有SQL区(共享服务器模式):存储的是在执行SQL语句时与每个会话或用户相关的私有信息。其他会话即使执行相同的SQL语句也不会使用这些信息。比如绑定变量、环境和会话参数。

  • 3、SQL和PL/SQL结果缓存:此高速缓存用于存储SQL查询或PL/SQL函数的结果,以加快其将来的执行速度。
  • 4、锁与其他控制结构:存储ORACLE例程内部操作所需的信息,如各种锁、闩、寄存器值等。

5.2 数据库高速缓冲区缓存(Database Buffer Cache)

也叫块缓存区,用于存放从数据文件读取的数据块,其大小由初始化参数DB_CACHE_SIZE决定。

工作原理是通过LRU队列(最近最少使用Least Recently Used)。查询时,Oracle会先把从磁盘读取的数据放入内存供所有用户共享,以后再查询相关数据时不用再次读取磁盘。插入和更新时,Oracle会先在该区域中缓存数据,之后批量写到硬盘中。通过块缓冲区,Oracle可以通过内存缓存提高磁盘的I/O性能。

数据高速缓存块由许多大小相等的缓存块组成,这些缓存块分为3大类:

  • 1)脏缓存块(Dirty buffers):脏缓存块中保存的是被修改过的缓存块。即当一条SQL语句对某个缓存块中的数据进行修改后,该缓存块就被标记为脏缓存块。最后该脏缓存块被DBWn进程写入到硬盘的数据文件中永久保存。
  • 2)命中缓存块(Pinned buffers):命中缓存块中保存的是最近正在被访问的缓存块。它始终被保留在数据高速缓存中,不会被写入数据文件。
  • 3)空闲缓存块(Free buffers):该缓存块中没有数据,等待被写入数据。oracle从数据文件中读取数据后,寻找空闲缓存块,以便写入其中。

Oracle通过2个列表(DIRTY、LRU)来管理缓存块:

  • 1)DIRTY列表中保存已经被修改但还没有被写入到数据文件中的脏缓存块。
  • 2)LRU列表中保存所有的缓存块(还没有被移动到DIRTY列表中的脏缓存块、空闲缓存块、命中缓存块)。当某个缓存块被访问后,该缓存块就被移动到LRU列表的头部,其他缓存块就向LRU列表的尾部移动。放在最尾部的缓存块就最先被移出LRU列表。

数据高速缓存的工作原理过程:

  • 1)ORACLE在将数据文件中的数据块复制到数据高速缓存之前,先在数据高速缓存中找空闲缓存块,以便容纳该数据块。Oracle将从LRU列表的尾部开始搜索,直到找到所需的空闲缓存块为止。
  • 2)如果先搜索到的是脏缓存块,将该脏缓存块移动到DIRTY列表中,然后继续搜索。如果搜索到的是空闲缓存块,则将数据块写入,然后将该缓存块移动到DIRTY列表的头部。
  • 3)如果能够搜索到足够的空闲缓存块,就将所有的数据块写入到对应的空闲缓存块中,搜索写入过程结束。
  • 4)如果没有搜索到足够的空闲缓存块,则ORACLE就先停止搜索,而是激活DBWn进程,开始将DIRTY列表中的脏缓存块写入到数据文件中。
  • 5)已经被写入到数据文件中的脏缓存块将变成空闲缓存块,并被放入到LRU列表中。执行完成这个工作后,再重新开始搜索,直到找到足够的空闲缓存块为止。

这里可以看出,如果你的高速缓冲区很小的,不停地写写,造成很大I/O开销。

块缓冲区可以配置1、2或3个缓冲池,默认只有第一个:

  • 1)默认池(Default pool):所有数据默认都在这里缓存,除非你在建表的时候指定 Store(buffer_pool keep) or Store(buffer_pool recycle)。使用LRU算法管理。
  • 2)保持池(Keep pool):缓存需要多次重用的数据,长期保存在内存中,缺省值为0。
  • 3)回收池(Recycle pool):用来缓存很少重用的数据,用完就释放,缺省值为0。

原来只有一个默认池,所有数据都在这里缓存。这样会产生一个问题:大量很少重用的数据会把需重用的数据“挤出”缓冲区,造成磁盘I/O增加,运行速度下降。后来分出了保持池和回收池根据是否经常重用来分别缓存数据。这三部分内存池需要手动确定大小,并且之间没有共享。例如:保持池中已经满了,而回收池中还有大量空闲内存,这时回收池的内存不会分配给保持池,这些池一般被视为一种非常精细的低级调优设备,只有所有其他调优手段大多用过之后才应考虑使用。

在9i之前,数据缓冲区的大小是由DB_BLOCK_BUFFER决定的,缓冲区的大小为DB_BLOCK_SIZE(Oracle数据块大小,创建数据库时设定好后续不能改变)和DB_BLOCK_BUFFERS(缓冲区块的个数)这两个参数的乘积,改变需重启数据库。之后的版本则是由参数DB_CACHE_SIZE及DB_nK_CACHE_SIZE确定。不同的表空间可以使用不同的块大小,在创建表空间中加入参数BLOCKSIZE指定该表空间数据块的大小,如果指定的是2k,则对应的缓冲区大小为DB_2K_CACHE_SIZE参数的值,如果指定的是4k,则对应的缓冲区大小为DB_4K_CACHE_SIZE参数的值,以此类推。如果不指定BLOCKSIZE,则默认为参数DB_BLOCK_SIZE的值,对应的缓冲区大小是DB_CACHE_SIZE的值。

数据库高速缓冲区缓存大小的建议可以参看内存缓冲区顾问v$db_cache_advice

打开或关闭该顾问

alter system set db_cache_advice=on|off|ready;

5.3、重做日志缓冲区(Redo Log Buffer Cache)

Oracle在DML或DDL操作改变数据写到数据库高速缓冲区缓存之前,先写入重做日志缓冲区,随后LGWR后台进程再把日志条目写到磁盘上的联机日志文件中。日志缓冲区的大小由初始化参数log_buffer决定大小。

以下情况触发LGWR进程将日志缓存数据写到联机日志文件中:

  • 1)每隔3秒
  • 2)缓存达到1MB或1/3满时
  • 3)用户提交时
  • 4)缓冲区的数据写入磁盘前

5.4、大池(Large Pool)

可以根据实际业务需要来决定是否在SGA区中创建大池。如果没有创建大池,则需要大量内存空间的操作将占用共享池的内存, 将对系统性能带来影响。

大池没有LRU队列,在共享服务器连接时,PGA的大部分区域(UGA)将放入大池(不包括堆栈区域),并行化的数据库操作、大规模的I/O及备份和恢复操作可能用到大池。大池由初始化参数LARGE_POOL_SIZE确定其大小。

5.5、流池(Stream Pool)

加强对流的支持,大小由参数STREAM_POOL_SIZE确定。流池(如果没有配置流池,则是共享池中至多10%的空间)用于缓存流进程在数据库间移动/复制数据时使用的队列消息。

5.6、Java池(Java Pool)

用于支持在数据库中运行java代码,大小由参数JAVA_POOL_SIZE确定。

6、 进程全局区(Porcess Global Area, PGA)

一个PGA是一块独占内存区域,Oracle进程以专有的方式用它来存放数据和控制信息。当Oracle进程启动时,PGA也就由Oracle数据库创建了。当用户进程连接到数据库并创建一个对应的会话时,Oracle服务进程会为这个用户专门设置一个PGA区,用来存储这个用户会话的相关内容。当这个用户会话终止时,系统会自动释放这个PGA区所占用的内存。这个PGA区对于数据库的性能有比较大的影响,特别是对于排序操作的性能。

PGA主要包含排序区、会话区、堆栈区和游标区四个部分。通常情况下,系统管理员主要关注的是排序区,在必要时需要手工调整这个排序区的大小。游标区是一个动态的区域,在游标打开时创建,关闭时释放,故在数据库开发时,不要频繁的打开和关闭游标可以改善数据库的性能。其他分区的内容管理员只需要了解其用途,日常的维护交给数据库系统来完成即可。

6.1、为排序设置合理的排序区大小

当用户需要对数据进行排序时,系统会将需要排序的数据保存到PGA中的一个排序区内,然后在这个排序区内对这些数据进行排序。如需要排序的数据有2M,那么排序区内必须至少要有2M的空间来容纳这些数据。然后排序过程中又需要有2M的空间来保存排序后的结果。由于系统从内存中读取数据比从硬盘中读取数据的速度要快几千倍,为此如果这个数据排序与读取的操作都能够在内存中完成,无疑可以在很大程度上提高数据库排序与访问的性能。如果这个排序的操作都能够在内存中完成,显然这是很理想的。但是如果PGA中的排序区容量不够,不能容纳排序后的数据,系统会从硬盘中获取一个空间,用来保存需要排序的数据。此时排序的效率就会降低许多。为此在数据库管理中,如果发现用户的很多操作都需要用到排序,那么为用户设置比较大的排序区,可以提高用户访问数据的效率。

在Oracle数据库中,这个排序区主要用来存放排序操作产生的临时数据。一般来说,这个排序区的大小占据PGA程序缓存区的大部分空间,这是影响PGA区大小的主要因素。在小型应用中,数据库管理员可以直接采用其默认的值。但是在一些大型的应用中,或者需要进行大量记录排序操作的数据库系统中,管理员可能需要手工调整这个排序区的大小,以提高排序的性能,这可以通过初始化参数SORT_AREA_SIZE来实现。

6.2、会话区保存着用户的权限等重要信息

会话区保存了会话所具有的权限、角色、性能统计等信息,通常都是由数据库系统自我维护,管理员不用干预。当用户进程与数据库建立会话时,系统会将这个用户的相关权限查询出来,保存在这个会话区内。用户进程在访问数据时,系统会核对会话区内的用户权限信息,看看其是否具有相关的访问权限。

6.3、堆栈区保存变量信息

保存着绑定变量、会话变量、SQL语句运行时的内存结构等重要的信息。通常都是由数据库系统自我维护,管理员不用干预。这些分区的大小,也是系统根据实际情况来进行自动分配的。当这个用户会话结束时,系统会自动释放这些区所占用的空间。

6.4、游标区

游标区是一个动态的区域。当用户执行游标语句打开游标时,系统会在PGA中创建游标区,当关闭游标时,这个区域就会被释放。创建与释放需要占用一定的系统资源,花费一定的时间,如果频繁的打开和关闭游标,就会降低语句的执行性能。所以在写语句时,游标最好不要频繁的打开和关闭。

初始化参数OPEN_CURSORS可以根据实际需要来设置,控制用户能够同时打开游标的数量。在确实需要游标的情况下,如果硬件资源支持的话,也可以放宽这个限制。

7、 用户全局区(User Global Area, UGA)

专用服务器模式下,进程和会话是一对一的关系,UGA被包含在PGA中,在共享服务器模式下,进程和会话是一对多的关系,所以UGA就不再属于PGA了,而会在大型池(Large Pool)中分配。但如果从大型池中分配失败,如大型池太小,或是根本没有设置大型池,则从共享池(Shared Pool)中分配。

8、实例的后台进程

8.1、重做日志写进程LGWR

Oracle使用快速提交的技术,保证系统的效率,并保证系统崩溃时所提交的数据可以得到恢复,引入系统改变号SCN。

SCN是单调递增的正整数,与Oracle内部时间戳对应,保证系统中数据的同步和读一致性。

发出commit命令后:

  • 1)服务器进程把提交的记录连同产生的SCN号一起写入重做日志缓存。
  • 2)LGWR把缓存中一直到提交的记录和SCN连续的写入联机重做日志文件中。在此之后,Oracle就能够保证即使在系统崩溃的情况下所有已提交的数据也可以得到恢复(联机重做日志文件在归档前不能被覆盖重写)。
  • 3)Oracle通知用户进程提交已经完成。
  • 4)服务器进程修改数据库高速缓存中的数据状态,释放资源和打开锁。

写日志要比写数据效率高,记录格式紧凑,I/O量少,顺序写入。

LGWR写入时机:

  • 1)事务被提交
  • 2)日志缓存中变化记录超过1MB
  • 3)日志缓存中的记录超过缓冲区容量的1/3
  • 4)DBWR写入数据文件之前
  • 5)每3秒钟

日志挖掘器( log miner)工具,可将日志文件中的内容转化为用户能够理解的正文信息。

8.2、数据库写进程DBWR/DBWn

Oracle实例允许启动最多10个数据库写进程DBW0~DBW9

DBWn写入时机:

  • 1)当脏缓冲区的数量超过了所设定的限额
  • 2)所设定的时间间隔已到
  • 3)当有进程需要数据库高速缓冲区却找不到空闲的缓冲区时
  • 4)当检查点发生时
  • 5)当某个表被删除或截断时
  • 6)当某个表空间被设置为只读时
  • 7)当对某个表空间进行联机备份时
  • 8)当某个临时表空间被设置为脱机状态或正常状态时

8.3、系统监视器进程SMON

当Oracle系统由于某种原因如断电,SGA中已经提交但还未被写入数据文件中的数据将丢失。当数据库重启时,系统监视器进程SMON将自动执行Oracle实例的恢复工作。

  • 1)执行前滚,将已提交到重做日志文件中但还未写到数据文件中的数据写到数据文件中。(通过SCN号识别提交记录)
  • 2)前滚完成后立即打开数据库,这时数据文件中可能还有一些没有提交的数据。(之所以这样安排,主要是为了提高系统的效率)
  • 3)回滚未提交的事务(数据)
  • 4)执行一些磁盘空间的维护工作

8.4、进程监视器进程PMON

当某个用户进程崩溃时(如未正常退出),进程监视器进程PMON将负责清理工作。

  • 1)回滚用户当前的事务
  • 2)释放用户所加的所有表一级和行一级的锁
  • 3)释放用户所有的其它资源

8.5、检查点进程CKPT

Oracle为了提高系统效率和保证数据库的一致性,引入检查点事件。

DBWR将SGA中所有已改变了的数据库高速缓冲区缓存中的数据(包括已提交的和未提交的)写到数据文件中时,将产生检查点事件。

保证了所有到检查点为止的变化了的数据都已经写到了数据文件中,在实例恢复时检查点之前的重做日志记录已经不再需要,从而加快了实例的恢复速度。

检查点事件发生时,Oracle要将检查点号写入数据文件头中,还要将检查点号、重做日志序列号、归档日志名称和SCN号都写入控制文件中。

过于频繁的检查点会使联机操作受到冲击,因此需要在实例的恢复速度和联机操作之间折中。(大多在20分钟以上)

检查点发生时机:

  • 1)重做日志的切换
  • 2)LOG_CHECKPOINT_TIMEOUT 这个延迟参数的到达
  • 3)相应字节(LOG_CHECKPOINT_INTERVAL* size of IO OS blocks)被写到当前的重做日志
  • 4)ALTER SYSTEM SWITCH LOGFILE命令
  • 5)ALTER SYSTEM CHECKPOINT命令

查看数据库的检查点号:

Select checkpoint_change# from v$database;

查看数据库当前的SCN号:

Select current_scn from v$database;

8.6、归档日志进程ARCH/ARCn

当数据库运行在归档日志模式下时,ARCH/ARCn进程将把日志切换后的联机重做日志文件中的数据复制到归档日志文件中,保证不会因致联机日志文件组的循环切换而导致日志数据丢失,从而保证数据库的可完全恢复。

归档日志文件是脱机的。

Oracle确保在一组重做日志的归档操作完成之前不会重新使用该组重做日志。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值