Buffer Cache

Buffer Cache是SGA区中专门用于存放从数据文件中读取的的数据块拷贝的区域。Oracle进程如果发现需要访问的数据块已经在buffer cache中,就直接读写内存中的相应区域,而无需读取数据文件,从而大大提高性能(内存的读取效率是磁盘读取效率的14000倍)。Buffer cache对于所有oracle进程都是共享的,即能被所有oracle进程访问。

一、CBC、Hash BucketHash Chain List

    CBC链,用来查找block是否在buffer cache中的时候,需要用到,用以快速定位Buffer。Oracle将buffer cache中所有的buffer通过一个内部的Hash算法运算之后,将这些buffer放到不同的 Hash Bucket中。每一个Hash Bucket中都有一个

Hash Chain List,通过这个list,将这个Bucket中的block串联起来,Hash Chain List是一个双向链表。

 

从图中我们可以看到,一个latch:cache buffers chains(CBC) 可以保护多个Hash Bucket,也就是说,如果我要访问某个block,我首先要获得这个latch,一个Hash Bucket对应一个Hash Chain List,而这个Hash Chain List挂载了一个或者多个Buffer Header。

二、Oracle对数据块的访问过程

1、对该Block运用Hash算法,得到Hash值。

2、获得cache buffers chains latch

3、到相应的Hash Bucket中搜寻相应Buffer Header

4、如果找到相应的Buffer Header,然后判断该Buffer的状态,看是否需要构造CR Block,或者Buffer处于pin的状态,最后读取。

5、如果找不到,就从磁盘读入到Buffer Cache中。(物理读)

latch:cache buffers chains的等待事件

在Oracle9i以前,如果其它用户进程已经获得了这个latch,那么新的进程就必须等待,直到该用户进程搜索完毕(搜索完毕之后就会释放该latch)。从Oracle9i开始 cache buffers chains latch可以只读共享,也就是说用户进程A以只读(select)的方式访问Block,这个时候获得了该latch,同时用户进程B也以只读的方式访问Block,那么这个时候由于是只读的访问,用户进程B也可以获得该latch。但是,如果用户进程B要以独占的方式访问Block,那么用户进程B就会等待用户进程A释放该latch,这个时候Oracle就会对用户进程B标记一个latch:cache buffers chains的等待事件。

latch:cache buffers chains解决:

1、优化SQL。大量逻辑读的SQL语句就有可能产生非常严重的latch:cache buffers chains等待,因为每次要访问一个block,就需要获得该latch,由于有大量的逻辑读,那么就增加了latch:cache buffers chains争用的机率。

2、Hash Bucket太少,需要更改_db_block_hash_buckets隐含参数。9i之后就基本不会出现这个问题了。

三、LRU List

1、LRU的引入

数据从DBF文件中加载到buffer cache的过程中,首先会使用Free的Buffer 来缓存DBF的Block。当数据库使用一段时间后,Buffer Cache中将不存在Free的Buffer,这个时候,应该使用什么样的Buffer来缓存数据块呢?

我们介绍下Buffer的几种状态。当buffer没有被使用的时候,状态是Free的,一旦缓存数据,状态立马变成clean的。如果这个buffer的数据被更改了,但是没有被提交,这个时候,状态就是dirty的。一旦提交,就会重新变成clean的。回到上面的问题,Free的Buffer使用完了,最合理的,应该是使用什么样的buffer呢?Oracle给我们的答案是:使用“最近使用最少的”clean块,做为替换对象!Oracle数据库的buffer cache是很大的,如果一个个去比较,寻找,效率是极低的。所以,oracle引入LRU的概念。

LRU是一个双向链表,LRU链表的两端就分别叫做最近使用端(the Most Recently Used MRU)和最近最少使用端(LRU)。如果一个用户进程发现某个block不在Buffer Cache中,那么用户进程就会从磁盘上将这个block读入Buffer Cache。在将block读入到Buffer Cache之前,首先要在LRU list上寻找Free的buffer,如果没有找到,就找最近最少使用端(LRU)的buffer,用以缓存数据。

2、LRU算法及改进

普通LRU算法的实现原理是每访问一个buffer,就把这个buffer移到MRU端。由于在oracle内部,访问buffer的频率非常高,不断的移动buffer在LRU中的位置开销相当大,并且不利于并发。所以oracle对LRU进行了改进。

(1) REPL链表

oracle对传统的LRU算法进行了改进。在每个buffer header增加了一个计数器(称为touch count,简称为TCH)和一个时间戳。每次访问buffer后,如果上次更新buffer header的TCH是在3秒之前,则对TCH加1,并把buffer header中的时间戳更新为当前时间。

oracle为REPL链表增加了一个字段cold_hd,可以理解为cold_hd后面的大部分buffer都是冷块。我们现在读取一个没有被缓存的data block,需要从REPL链表上得到一个buffer来缓存当前的data block。首先从LRU端获取一个buffer,如果是一个冷快(通过TCH来判断),则使用这个buffer缓存当前的data block,并把这个buffer header移到cold_hd的位置,更新TCH为1;如果是一个热快(通过TCH来判断),把这个buffer header移到MRU端,并更新TCH为原来的一半,然后继续检查LRU端的buffer是否是一个冷块,直到找到一个冷块为止。

(2) REPLAX链表

在REPL中淘汰一个buffer需要很多操作,比如判断是否被锁住,是否是dirty块。相对来说,REPL淘汰一个buffer是一个重量级操作。为此,oracle 增加了另外一个链表REPLAX(replacement list auxilitary),这个链表里的所有buffer可以立即被淘汰,不用检查是否是dirty buffer、是否被pinned。从REPLAX链表淘汰buffer是轻量级操作。

oracle启动时,所有buffer header都挂在REPLAX上,随着计数器的增加,这些buffer header会被从REPLAX移到REPL中。当DBWn把dirty块写入到磁盘后,这些buffer会移到到REPLAX。

3、全表扫描

对大表全表扫描时,如果上述改进LRU算法的淘汰策略,会导致所有热快被立即换出。oracle首先会对表大小进行评估,进行大表进行全表扫描时,对大表的buffer采用不同的淘汰策略。

(1)表大小> cache的10%。第一次扫描当作大表来对待,计数器不增加,并且buffer header放入REPLAX链表。如果表数据还在缓存的情况下又进行的全部扫描,则认为这个把这个表当作小表扫描来对待,增加计数器。

(2)表大小> cache的25%。计数器的值不会增加,且表对应的buffer header只会出现在REPLAX链表上。

在create table时,使用cache子句也会影响buffer的淘汰侧路。cache子句包括3个选项CACHE、NOCACHE、CACHE和READS。CACHE适用于经常被访问的小表,NOCACHE适用于大表和访问频次低的表,CACHE READS适用于包含LOB的表。

四、LRU Write List

用户提交commit时, 脏buffer并没有写入dbf文件,而只是记入了redo log中。真正将脏buffer写入到dbf文件中的是DBWRITER。而DBWRITER是怎么个什么样的后台进程呢?

1、DBWRITER进程

Oracle最繁忙的两个后台进程之一,负责将脏buffer写入dbf中。

2、DBWRITER触发条件

后台进程DBwriter,在以下几种条件下触发:

(1)每隔一个时间段触发(例如3秒)。

(2)PGA没有找到干净的块,触发。

(3)当达到扫描块数限制后还没有找到空闲buffer,就需要通知DBW0将脏缓存回写到磁盘。

3、LRU Writer List

有了DBWRITER,那么它需要怎么选择buffer cache中的buffer写入dbf中呢?Oracle引入了LRUW链表。LRUW将脏块按照被访问的频率链起来,方便DBWRITER从冷端开始写入脏buffer。

五、Buffer的状态分析

x$bh  每一个buffer在这个表中都有一行数据。

Buffer Cache中的Buffer有多种状态(x$bh):

0, FREE, no valid block image

1, XCUR,单实例的数据库,直接对应数据库的块。增删改查都需要对该buffer进行操作。

2, SCUR,  RAC多实例的数据库才会存在。

3, CR, 当XCUR还没有提交时,其他会话进行读操作时,oracle构造出来的buffer。读完,就没有存在的意义了。

4, READ, oracle正在加载block时,为read状态。

7,WRITE  DBWriter正在写。

Buffer Cache的更多相关文章

  1. 相克军_Oracle体系_随堂笔记005-Database buffer cache

    本章主要阐述SGA中的Database buffer cache. Buffer cache { 1.pin (读写瞬间的状态) 2.clean 3.dirty 4.unused } --Databa ...

  2. Buffer cache hit ratio性能计数器真的可以作为内存瓶颈的判断指标吗?

    Buffer cache hit ratio官方是这么解释的:“指示在缓冲区高速缓存中找到而不需要从磁盘中读取的页的百分比.” Buffer cache hit ratio被很多人当做判断内存的性能指 ...

  3. Oracle buffer cache

    Buffer Cache buffer cache 结构图 HASH链 ORACLE使用HASH算法,把buffer cache中每个buffer的buffer header串联起来,组成多条hash ...

  4. Oracle优化 -- 关于Database Buffer Cache相关参数DB_CACHE_SIZE的优化设置

    select size_for_estimate, buffers_for_estimate ,ESTD_PHYSICAL_READ_factor,ESTD_PHYSICAL_READS from v ...

  5. 【转】Linux 查看内存(free buffer cache)

    转自:http://elf8848.iteye.com/blog/1995638 Linux下如何查内存信息,如内存总量.已使用量.可使用量.经常使用Windows操作系统的朋友,已经习惯了如果空闲的 ...

  6. 配置和使用buffer cache

    存放从磁盘读取的数据.排序和并行读不会使用buffer cache 可以从v$db_cache_advice或者buffer cache的命中率来检查buffer cache设置是否合理 查看v$db ...

  7. buffer cache中,各个object对象占用的buffer blocks

    buffer cache中,各个object对象占用的buffer blocks: COLUMN OBJECT_NAME FORMAT A40 COLUMN NUMBER_OF_BLOCKS FORM ...

  8. Linux-内存管理机制、内存监控、buffer/cache异同

    在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将 ...

  9. Page cache和Buffer cache[转1]

    http://www.cnblogs.com/mydomain/archive/2013/02/24/2924707.html Page cache实际上是针对文件系统的,是文件的缓存,在文件层面上的 ...

随机推荐

  1. CE程序

    注:开发工具用VS2008 安装Windows mobile设备中心进行调试. 项目平台 1.窗体属性设置,然后将size改成238, 320 2.效果 3.调试过程选择“部署” 4.配置文件的简单读 ...

  2. 学习opencv

    图像缩放 cv::Mat src_img = cv::imread(); ; cv::Mat dst_img1; cv::Mat dst_img2(src_img.rows*0.5, src_img. ...

  3. spring mvc 4 校验

    一.controller中添加: @ResourceGatewayValidator gatewayValidator; @RequestMapping(value = "/gateway/ ...

  4. ubuntu下postgreSQL安装配置

    一.安装并配置,并设置远程登陆的用户名和密码 1.安装postgreSQL sudo apt-get update sudo apt-get install postgresql-9.4 在Ubunt ...

  5. 定位form光标行

    In AX2009 if you call the research() method on a form passing true, the cursor position within a gri ...

  6. 使用Maven加载项目有Dubbo框架时出现的常见异常情况

    异常描述:            The matching wildcard is strict, but no declaration can be found for element 'dubbo ...

  7. 【原创】【2015最新】微信公众平台开发手把手入门之一:缘起微信公众号(PHP,MYSQL, BAE)

    最近因为业务的需要,老板布置做了两个月简单的的微信公众平台开发,从网上搜了一些资料,实话说资料不多. 在参考学习的过程中也遇到了不少难缠的小问题,虽然不难逾越,但是确实浪费了时间. 我发现网上仅有不多 ...

  8. ant批量执行Jmeter脚本

    JDK,Jmeter默认已经装了 ANT下载:http://ant.apache.org/bindownload.cgi ant环境变量需要配置 ant_home,你解压之后的地址 然后PATH环境变 ...

  9. iOS 为iPhone和iPad创建不同的storyboard

    复制Main.storyboard,重命名为Main_iPad.storyboard 在info.plist文件中添加 Main storyboard file base name (iPad) -- ...

  10. (转载)afxres找不到问题

    在试用VS2010时一个问题困扰了我,就是打开c++项目后,rc的dialog进不去,没法拖控件,把我给抓狂的...而且网上大部分说的都是Directions的问题..我的问题明显不是这个问题. 于是 ...