Buffer Cache
Buffer Cache
Buffer Cache是SGA区中专门用于存放从数据文件中读取的的数据块拷贝的区域。Oracle进程如果发现需要访问的数据块已经在buffer cache中,就直接读写内存中的相应区域,而无需读取数据文件,从而大大提高性能(内存的读取效率是磁盘读取效率的14000倍)。Buffer cache对于所有oracle进程都是共享的,即能被所有oracle进程访问。
一、CBC、Hash Bucket与Hash 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的更多相关文章
- 相克军_Oracle体系_随堂笔记005-Database buffer cache
本章主要阐述SGA中的Database buffer cache. Buffer cache { 1.pin (读写瞬间的状态) 2.clean 3.dirty 4.unused } --Databa ...
- Buffer cache hit ratio性能计数器真的可以作为内存瓶颈的判断指标吗?
Buffer cache hit ratio官方是这么解释的:“指示在缓冲区高速缓存中找到而不需要从磁盘中读取的页的百分比.” Buffer cache hit ratio被很多人当做判断内存的性能指 ...
- Oracle buffer cache
Buffer Cache buffer cache 结构图 HASH链 ORACLE使用HASH算法,把buffer cache中每个buffer的buffer header串联起来,组成多条hash ...
- Oracle优化 -- 关于Database Buffer Cache相关参数DB_CACHE_SIZE的优化设置
select size_for_estimate, buffers_for_estimate ,ESTD_PHYSICAL_READ_factor,ESTD_PHYSICAL_READS from v ...
- 【转】Linux 查看内存(free buffer cache)
转自:http://elf8848.iteye.com/blog/1995638 Linux下如何查内存信息,如内存总量.已使用量.可使用量.经常使用Windows操作系统的朋友,已经习惯了如果空闲的 ...
- 配置和使用buffer cache
存放从磁盘读取的数据.排序和并行读不会使用buffer cache 可以从v$db_cache_advice或者buffer cache的命中率来检查buffer cache设置是否合理 查看v$db ...
- buffer cache中,各个object对象占用的buffer blocks
buffer cache中,各个object对象占用的buffer blocks: COLUMN OBJECT_NAME FORMAT A40 COLUMN NUMBER_OF_BLOCKS FORM ...
- Linux-内存管理机制、内存监控、buffer/cache异同
在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将 ...
- Page cache和Buffer cache[转1]
http://www.cnblogs.com/mydomain/archive/2013/02/24/2924707.html Page cache实际上是针对文件系统的,是文件的缓存,在文件层面上的 ...
随机推荐
- [Maven] - Eclipse "maven compiler plugin" 冲突解决
刚安装最新的Maven 3.2.5,在eclipse中使用maven的Run As->Maven Install,总会提示: Failed to execute goal org.apache. ...
- 项目管理-Kick OFF 简称KO
KO的内容包括以下几个过程: 1.项目背景 我们项目在哪里?说过去,做项目之前的“悲惨境地”,明确问题根源在哪里,明白为什么要做这个项目. 2.项目意义.目的与目标 我们项目去哪里?说将来,项目完成之 ...
- DHTMLX-Form
DHTMLX-Form dhtmlxForm提供了一个标准形式与一些有用的补充,如不同风格,使用的数据从客户端和服务器端,与其他dhtmlx组件的集成.验证等. 例子 <!DOCTYPE htm ...
- ASP.NET管道
以IIS 6.0为例,在工作进程w3wp.exe中,利用Aspnet_ispai.dll加载.NET运行时(如果.NET运行时尚未加载).IIS 6引入了应用程序池的概念,一个工作进程对应着一个应用程 ...
- sublime text 3 license 2016.05
补充:2016.05 最近经过测试,3个注册码在新版3103的sublime上已经不可用了. 现补充两枚新版的license key: -– BEGIN LICENSE -– Michael Barn ...
- SQL SERVER 导出数据,数据与结构,结构
1.右键数据库->任务->生成脚本 2.选择数据库对象,可以整个表,也可以选择部分表 3.下一步,设置脚本编写选项.选择高级,在高级中,倒数第二项,'要编写脚本的数据的类型'中,可以选择导 ...
- git的基础介绍和使用
git工作原理 git的工作原理还是比较简单的,当我们创建了本地代码仓库后,会在本地代码仓库的根目录中生成一个.git的隐藏文件. .git为一个文件目录,又叫做版本库.在本地代码仓库文件夹中,除.g ...
- Solr整合Ansj中文分词器
Ansj的使用和相关资料下载参考:http://iamyida.iteye.com/blog/2220833 参考 http://www.cnblogs.com/luxh/p/5016894.html ...
- Shogun网站上的关于主流机器学习工具包的比较
Shogun网站上的关于主流机器学习工具包的比较: http://www.shogun-toolbox.org/page/features/ created last updated main l ...
- PHP二维码生成的方法(google APi,PHP类库,libqrencode等)
原文地址: http://blog.csdn.net/liuxinmingcode/article/details/7910975 ================================== ...