目录
一、前言
1前面我们已经说过,实例包含一块内存区域和一组后台进程,它们又是由哪些部分组成的呢?
二、系统全局域
实例的内存区域,我们称之为系统全局域(System Global Area),简称SGA。它是所有服务器进程和后台进程共享的,包含数据库缓冲区缓存(Database Buffer Cache)、共享池(Shared Pool)、重做日志缓冲区(Redo Log Buffer)、大池(Large Pool)、Java池(Java Pool)、流池(Stream Pool),其中有些是必须有的,有些可不必有。
2.1 、数据库缓冲区缓存
作用:缓存了从磁盘上检索的数据块。
工作原理:使用LRU(最近最少使用 Least Recently Used )算法。查询时,Oracle会先把从磁盘读取的数据放入内存供所有用户共享,以后再查询相关数据时不用再次读取磁盘。插入和更新时,Oracle会先在该区中缓存数据,之后批量写到硬盘中。通过块缓冲区,Oracle可以通过内存缓存提高磁盘的I/O性能(注:磁盘I/O的速率是毫米级的,而内存I/O的速率为纳秒级)
数据高速缓存块由许多大小相等的缓存块组成,这些缓存块的大小和OS块大小相同。 这些缓存块分为3大类
- 脏缓存块( Dirty buffers ):脏缓存块中保存的时被修改过的缓存块。即当一条SQL语句对某个缓存块中的数据进行修改后,该缓存块就被标记为脏缓存块。最后该脏缓存块被DBWn进程写入到硬盘的数据文件中,永久保留起来。
- 命中缓存块( Pinned buffers ):命中缓存块中保存的是最近正在被访问的缓存块。它始终被保留中数据高速缓存中,不会被写入数据文件。
- 空闲缓存块(Free buffers):该缓存块中没有数据,等待被写入数据。oracle从数据文件中读取数据后,寻找空闲缓存块,以便写入其中。
Oracle 通过 2 个列表(DIRTY、LRU)来管理缓存块
1、DIRTY 列表中保存已经被修改但还没有被写入到数据文件中的脏缓存块。
2、LRU列表中保存所有的缓存块(还没有被移动到DIRTY列表中的脏缓存块、空闲缓存块、命中缓存块)。当某个缓存块被访问后,该缓存块就被移动到LRU列表的头部,其他缓存块就向LRU列表的尾部移动。放在最尾部的缓存块就最先被移出LRU列表。
数据高速缓存的工作原理过程是:
A、ORACLE在将数据文件中的数据块复制到数据高速缓存中之前,先在数据高速缓存中找空闲缓存块,以便容纳该数据块。Oracle 将从LRU列表的尾部开始搜索,直到找到所需的空闲缓存块为止。
B、如果先搜索到的是脏缓存块,将该脏缓存块移动到DIRTY列表中,然后继续搜索。如果搜索到的是空闲缓存块,则将数据块写入,然后将该缓存块移动到DIRTY列表的头部。
C、如果能够搜索到足够的空闲缓存块,就将所有的数据块写入到对应的空闲缓存块中。则搜索写入过程结束。
D、如果没有搜索到足够的空闲缓存块,则ORACLE就先停止搜索,而是激活DBWn进程,开始将DIRTY列表中的脏缓存块写入到数据文件中。
E、已经被写入到数据文件中的脏缓存块将变成空闲缓存块,并被放入到LRU列表中。执行完成这个工作后,再重新开始搜索,直到找到足够的空闲缓存块为止。
这里可以看出,如果你的高速缓冲区很小的,不停地写写,造成很大I/O开销。
块缓冲区可以配置1、2或3个缓冲池,默认只有一个
- 默认池(Default pool):所有数据默认都在这里缓存,除非你在建表的时候指定 Store(buffer_pool keep) or Store(buffer_pool recycle)。使用LRU算法管理。
- 保持池(Keep pool):缓存需要多次重用的数据,长期保存内存中,缺省值为0。
- 回收池(Recycle pool):用来缓存很少重用的数据,用完就释放,缺省值为0。
原来只有一个默认池,所有数据都在这里缓存。这样会产生一个问题:大量很少重用的数据会把需重用的数据“挤出”缓冲区,造成磁盘I/O增加,运行速度下降。后来分出了保持池和回收池根据是否经常重用来分别缓存数据。这三部分内存池需要手动确定大小,并且之间没有共享。例如:保持池中已经满了,而回收池中还有大量空闲内存,这时回收池的内存不会分配给保持池,这些池一般被视为一种非常精细的低级调优设备,只有所有其他调优手段大多用过之后才应考虑使用。
在9i之前,数据缓冲区的大小是由DB_BLOCK_BUFFER确定,之后的版本中,是由参数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的值。
2.2、共享池
共享池是一块比较复杂的内存结构,它的区域划分还跟用户进程连接数据库的模式有关(专用服务器连接和共享服务器连接,本篇不做讲解)。包含两个部分库缓存(Library Cache)、数据字典缓存(Data Dictionary Cache)、结果高速缓存、锁与其他控制结构
1、 数据字典缓存(data dictionary cache),用于存储经常使用的数据字典信息。比如(表的定义、用户名、口令、权限、数据库的结构等)。Oracle运行过程中经常访问该缓存以便解析SQL语句,确定操作的对象是否存在,是否具有权限等。如果不在数据字典缓存中,服务器进程就从保存数据字典信息的数据文件中将其读入到数据字典缓存中。数据字典缓存中保存的是一条一条的记录(就像是内存中的数据库),而其他缓存区中保存的是数据块信息。
2、 库缓冲区(Library Cache): 库缓存的目的就是保存最近解析过的SQL语句、PL/SQL过程和包。这样一来,Oracle在执行一条SQL语句、一段PL/SQL 过程和包之前,首先在“库缓存”中搜索,如果查到它们已经解析过了,就利用“库缓存”中解析结果和执行计划来执行,而不必重新对它们进行解析,显著提高执行速度和工作效率。
ORACLE将每一条SQL语句分解为可共享、不可共享的两部分。
a) 共享SQL区:存储的是最近执行的SQL语句、解析后的语法树和优化后的执行计划。这样以后执行相同的SQL语句就直接利用在共享SQL区中的缓存信息,不必重复语法解析了。Oracle在执行一条新的SQL语句时,会为它在共享SQL区中分配空间,分配的大小取决于SQL语句的复杂度。如果共享SQL区中没有空闲空间,就利用LRU算法,释放被占用的空间。
b) 私用SQL区(共享模式时):存储的是在执行SQL语句时与每个会话或用户相关的私有信息。其他会话即使执行相同的SQL语句也不会使用这些信息。比如(绑定变量、环境和会话参数)。
3、结果高速缓存:结果高速缓存包含 SQL 查询结果高速缓存和 PL/SQL 函数结果高速缓存。此高速缓存用于存储 SQL 查询或 PL/SQL 函数的结果,以加快其将来的执行速度。
4、锁与其他控制结构:存储ORACLE例程内部操作所需的信息。比如(各种锁、闩、寄存器值)。
2.3、重做日志缓冲区(Redo log buffer)
作用:用于存放日志条目,日志条目就是记录对数据的改变。当这块区域用光时,后台进程LGWR把日志条目写到磁盘上的联机日志文件中。它由初始化参数log_buffer决定大小。同样的道理下,日志缓冲区应该稍微大点,特别是有长时间运行的事务的时候,可以大量减少I/O。
2.4、大池(Large pool)
大池由初始化参数LARGE_POOL_SIZE确定大小,可以使用ALTER SYSTEM语句来动态改变大池的大小,是可选项,DBA可以根据实际业务需要来决定是否在SGA区中创建大池。如果没有创建大池,则需要大量内存空间的操作将占用共享池的内存, 将对SHARED POOL造成一定的性能影响,而LARGE POOL是起着这种功能隔离作用的一块区域。
ORACLE 需要大量内存的操作有:
A、数据库备份和恢复,如RMAN某些情况下用于磁盘IO缓冲区
B、并行化的数据库操作,存放进程间的消息缓冲区
C、共享服务器模式下UGA在大池中分配(如果设置了大池)
D、执行大量排序操作的时候
2.5、Java池(Java pool)
用于支持在数据库中运行java代码,一般由java_pool_size控制
2.6、流池(Stream pool)
加强对流的支持,一般由stream_pool_size控制。流池(或者如果没有配置流池,则是共享池中至多10%的空间)会用于缓存流进程在数据库间移动/复制数据时使用的队列消息。
三、后台进程
常见的后台进程包含System Monitor(SMON)、Process Monitor(PMON)、检查点(CKPT)、数据库写入器(DBWn)、日志写入器(LGWR)、归档日志进程(ARCn),还有一些其他后台进程Manageability Monitor(MMON)、MMNL、ADDM、MMAN、LREG
3.1、System Monitor(SMON)
主内,监控实例内部,实例恢复,如整理碎片,清理不使用的临时段。安装和打开数据库也是由此进程完成的。
3.2、Process Monitor(PMON)
进程监视器,主外,监控用户连接。主要监视服务器进程。前面提到过,专有服务器体系模式下,用户进程和服务器进程是一对一的关系,如果某个会话发生异常,PMON会销毁对应的服务器进程,回滚未提交的事务,并回收会话专有的PGA内存区域。
在用户进程失败时执行进程恢复
清除数据库缓冲区高速缓存
释放该用户进程使用的资源
监视会话是否发生空闲会话超时
将数据库服务动态注册到监听程序
3.3、检查点(CKPT)
周期性触发,更新检查点信息,更新到控制文件和每个数据文件头部。可以手动设置。
3.4、数据库写入器(DBWn)
将Database Buffer Cache中的脏块写入数据文件。它是一个很懒的后台进程,执行commit时,并不能触发它执行写脏操作。
执行时间点:
1)没有任何可用缓冲区
2)脏缓冲区过多
3)三秒超时
4)遇到检查点
3.5、日志写入器(LGWR)
将Redo Log Buffer中日志写入在线重做日志文件。它是一个很勤快的进程,每当执行commit时,都会被触发。
触发条件:
1、用户提交commit
2、有三分之一的log buffer未被写入磁盘
3、有大于1M的log buffer未被写入磁盘
4、每隔三秒
5、DBWn需要写入的数据的SCN大于LGWR记录的SCN,触发LGWR写入,日志写入优先(Write-Ahead-Log)
3.6、归档日志进程(ARCn)
将写满后的redo log写入到归档日志中。只有开启归档模式,此进程才会工作。
3.7、其它进程
MMON: 自我监视和自我管理支持进程。实例在运行中,会收集大量有关实例活动和性能的统计数据,这些数据会收集到SGA中,MMON定期从SGA中捕获这些统计数据,并将其写入到数据字典中,便于后续对这些快照进行分析。(默认情况,MMON每隔一个小时收集一次快照)。
MMNL: MMON辅助进程。
ADDM: 自动数据库诊断监视器。
MMAN: 自动内存管理。
LREG: 监听注册进程。