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. atom 调用g++编译cpp文件

    atom 有script插件可以直接调用很多编译器,试了很多次一直出问题找不到文件,查了文档之后发现script只支持OSX和linux. 所以,还是使用gpp-compiler比较靠谱 gpp-co ...

  2. 【SFTP】使用Jsch实现Sftp文件上传-支持断点续传和进程监控

    JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...

  3. fMRI数据分析处理原理及方法(转载)

    原文地址:http://www.cnblogs.com/minks/p/4889497.html 近年来,血氧水平依赖性磁共振脑功能成像(Blood oxygenation level-depende ...

  4. Tomcat服务器重启失败:The server may already be running in another process, or a system process may be using the port.

    在控制台重启Tomcat服务器,报错如下: 原因分析: You've another instance of Tomcat already running. You can confirm this ...

  5. servlet简单用法和配置示例及说明

    学习原因和目的:   我如今所接触的项目都是bs模式的web应用,而里边基本上都是用的spring MVC和前台交互,servlet貌似用的很少.   但是即便是用spring和spring MVC, ...

  6. 为了让你的网页能在更多的服务器上正常地显示,还是加上“SET NAMES UTF8”吧

    Repinted:http://blog.csdn.net/class1/archive/2006/12/30/1469298.aspx 为了让你的网页能在更多的服务器上正常地显示,还是加上“SET ...

  7. jquery mobile 登陆后页面验证

    调用 pagebeforechange方法 $(document).bind("pagebeforechange", function (e, data) { if (typeof ...

  8. C#接口显示实现在实际开发中的作用

    摘要 任何一个C#入门的程序员都知道——当一个类型在实现接口的时候,有两种方法实现:显式实现.隐式实现.而且大家也都知道,当一个类型实现的两个接口存在相同成员定义时,显示实现可以解决这种情况. 但是, ...

  9. 一些常用的sql语句

    1.查询表里的null值:is null 和 is not null  select*from student where email is null       返回的该表里面邮箱为null的结果集 ...

  10. 64位电脑上配置mysql-connector-odbc的方法

    在系统盘搜索odbcad32,选择在C:\Windows\SysWOW64内的文件