在将数据块读入到SGA中,他们的缓冲区被放置在悬挂散列存储桶的链表中(散列链),这种内存结构由大量 子cache buffers chains锁存器(也称为散列锁存器或CBC锁存器)保护。





Buffer Cache概述

Buffer Cache是SGA的一部分,Oracle利用Buffer Cache来管理data block,Buffer Cache的最终目的就是尽可能的减少磁盘I/O。Buffer Cache中主要有3大结构用来管理Buffer Cache。





Hash Bucket与Hash Chain List

Oracle将buffer cache中所有的buffer通过一个内部的Hash算法运算之后,将这些buffer放到不同的 Hash Bucket中。每一个Hash Bucket中都有一个

Hash Chain List,通过这个list,将这个Bucket中的block串联起来。









下面举个简单的例子来介绍一下Hash 算法,Oracle的Hash 算法肯定没这么简单,具体算法只有Oracle公司知道。

•      一个简单的mod函数 ,我们去mod 4

Ø  1 mod 4 = 1

Ø  2 mod 4 = 2

Ø  3 mod 4 = 3

Ø  4 mod 4 = 0

Ø  5 mod 4 = 1

Ø  6 mod 4 = 2

Ø  7 mod 4 = 3

Ø  8 mod 4 = 0

……………省略…………………..

那么这里就相当于创建了4个Hash Bucket

如果有如下block:

blcok :DBA(1,1)  ------> (1+1) mod 4 =2  

block :DBA(1,2)  ------> (1+2) mod 4 =3

block :DBA(1,3)  ------> (1+3) mod 4 =0

block :DBA(1,4)  ------> (1+4) mod 4 =1

block :DBA(1,5)  ------> (1+5) mod 5 =2

………........省略…………………....

 

比如我要访问block(1,5),那么我对它进行Hash运算,然后到Hash Bucket为2的这个Bucket里面去寻找,Hash Bucket 为2的这个Bucket 现在有2个block,

这2个block是挂在Hash Chain List上面的









希望在散列链上添加,删除,搜索,检索,读取,或修改块的进程首先获得cache buffers chains latch,从而保护链上的缓冲区。

这样做可以保证独占的访问,并防止其他进程接下来读取或改变同一个链。为了完整性因此牺牲了并发性。

从图中我们可以看到,一个latch:cache buffers chains(x$bh.hladdr) 可以保护多个Hash Bucket,也就是说,如果我要访问某个block,我首先要获得这个latch,

一个Hash Bucket对应一个Hash Chain List,

而这个Hash Chain List挂载了一个或者多个Buffer Header。

Hash Bucket的数量受隐含参数_db_block_hash_buckets的影响,

Latch:cache buffers chains的数量受隐含参数_db_block_hash_latches的影响





Hash Bucket的数量受隐含参数_db_block_hash_buckets的影响,

Latch:cache buffers chains的数量受隐含参数_db_block_hash_latches的影响









SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ

  FROM x$ksppi x, x$ksppcv y

 WHERE x.inst_id = USERENV('Instance')

   AND y.inst_id = USERENV('Instance')

   AND x.indx = y.indx

   AND x.ksppinm LIKE '%_db_block_hash%'  2    3    4    5    6  ;





NAME       VALUE DESCRIB

------------------------------ ---------- ------------------------------

_db_block_hash_buckets       16384 Number of database block hash  buckets





_db_block_hash_latches       1024 Number of database block hash  Latches





可以用下面查询计算cache buffers chains latch的数量:

SQL> select count(*) from v$latch_children a,v$latchname b where a.latch#=b.latch# and b.name='cache buffers chains';





  COUNT(*)

----------

      1024





根据我们的查询,那么一个cache buffers chains latch 平均下来要管理

Select 16384/1024 from dual 16个块,那么现在我们随意的找一个latch,来验证一下前面提到的结构图。





SQL> select * from (select hladdr,count(*) from x$bh  group by hladdr) where rownum<=5;





HLADDR   COUNT(*)

-------- ----------

2D32792C  3

2D3279A8  4

2D327A24  4

2D327AA0  6

2D327D1C  3

我们查询latch address 为2D327AA0 所保护的data block





SQL> select hladdr,obj,dbarfil,dbablk, nxt_hash,prv_hash from x$bh where hladdr='2D327AA0' order by obj;





HLADDR OBJ    DBARFIL  DBABLK NXT_HASH PRV_HASH

-------- ---------- ---------- ---------- -------- --------

2D327AA0  2
    1    72670 2D327CFC 2D327CFC

2D327AA0       5841     1   11705 2D327D14 2D327D14

2D327AA0       6470     2    5969 2D327CEC 2D327CEC

2D327AA0      75313     2   58025 2D327CBC 2D327CBC

2D327AA0      75313     2   58258 2D327CDC 2D327CDC

2D327AA0      75347     2   66701 2D327CB4 2D327CB4





已选择6行。





请观察DBA(1,72670),它的NXT_HASH与PRV_HASH相同,也就是说DBA(1,72670)挂载在只包含有1个data block的 Hash Chain上。









当一个用户进程想要访问Block(1,72670):

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





l  获得cache buffers chains latch





l  到相应的Hash Bucket中搜寻相应Buffer Header





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





l  如果找不到,就从磁盘读入到Buffer Cache中。





在Oracle9i以前,如果其它用户进程已经获得了这个latch,那么新的进程就必须等待,直到该用户进程搜索完毕(搜索完毕之后就会释放该latch)。从Oracle9i开始 cache 

buffers chains latch可以只读共享,也就是说用户进程A以只读(select)的方式访问Block(84,615093),这个时候获得了该latch,同时用户进程B也以只读的方式访问Block

(765,1259399),那么这个时候由于是只读的访问,用户进程B也可以获得该latch。但是,如果用户进程B要以独占的方式访问Block(765,1259399),那么用户进程B就会等待用户进

程A释放该latch,这个时候Oracle就会对用户进程B标记一个latch:cache buffers chains的等待事件。





我们遇到了latch:cache buffers chains该怎么办?





l  不够优化的SQL。大量逻辑读的SQL语句就有可能产生非常严重的latch:cache buffers chains等待,因为每次要访问一个block,就需要获得该latch,由于有大量的逻辑读,那

么就增加了latch:cache buffers chains争用的机率





2.Hash Bucket太少,需要更改_db_block_hash_buckets隐含参数。其实在Oracle9i之后,我们基本上不会遇到这个问题了,除非遇到Bug。所以这个是不推荐的,记住,在对





Oracle的隐含参数做修改之前一定要咨询Oracle Support。

<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal;">
</span></span>

												

Buffer Cache 原理的更多相关文章

  1. BUFFER CACHE和SHARED POOL原理

    http://blog.csdn.net/wanghai__/article/details/4881492 Buffer Cache LRU与Dirty List 在Buffer Cache中,Or ...

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

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

  3. Buffer Cache

    Buffer Cache Buffer Cache是SGA区中专门用于存放从数据文件中读取的的数据块拷贝的区域.Oracle进程如果发现需要访问的数据块已经在buffer cache中,就直接读写内存 ...

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

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

  5. Oracle buffer cache与相关的latch等待事件

    buffer cache与相关的latch等待事件 1.buffer cache 2.latch:cache buffers lru chain 3.latch:cache buffers chain ...

  6. Buffer cache 的调整与优化

    Buffer cache 的调整与优化 -============================== -- Buffer cache 的调整与优化(一) --==================== ...

  7. 清理buffer/cache/swap的方法梳理

    一.缓存机制介绍 在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果 ...

  8. linux下的缓存机制及清理buffer/cache/swap的方法梳理 (转)

    一.缓存机制介绍 在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果 ...

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

    SQL Server中对于Buffer cache hit ratio的理解: Buffer cache hit ratio官方是这么解释的:“指示在缓冲区高速缓存中找到而不需要从磁盘中读取的页的百分 ...

随机推荐

  1. rsyslog同步history日志(转载)

    前言 由于公司业务是由公司内部开人员及外包团队共同开发,所以需要使用rsyslog对history日志做收集.审计.虽然搭建及配置非常简单,但是在日常运维工作中很实用,所以记录下,方便日后快速搭建.如 ...

  2. C# 利用反射查看类的信息

    using System; using System.Collections; using System.Collections.Generic; using System.Reflection; u ...

  3. [原创+实战+钓鱼]setoolkit+映射

    所需工具:setoolkit,花生壳 (此方法主要针对没有服务器,没有空间的攻击者.有服务器或者空间可以直接上传setoolkit的生成源码到服务器或者空间.) 1.setoolkit克隆一个站点 | ...

  4. AndroidUI开源组件库BottomView 第三方自定义UI控件

    这里分享一个Android的非常经典实用而且简单方便的第三方UI控件库:BottomView(小米的米UI也用到了这个) 原文  http://blog.csdn.net/opzoonzhuzheng ...

  5. Linux下rar unrar的安装

    Linux下rar unrar的安装: 以3.8.0版本为例,如果是64位平台,执行以下命令,也可以去官方网站:)下载最新版: wget http://www.rarlab.com/rar/rarli ...

  6. input text输完自动跳到下一个

    应用场景: 短信验证码输入 效果: input输入框,输入完以后自动跳转到下一个 思路: 四个输入框 进入聚焦到第一个输入框 第一个输入框输完一个字符后自动聚焦到下一个输入框 1.四个输入框 < ...

  7. SpringMvc之@RequestParam详解

    @RequestParam是传递参数的. @RequestParam用于将请求参数区数据映射到功能处理方法的参数上. public String queryUserName(@RequestParam ...

  8. github 预览html

    在网址前加 http://htmlpreview.github.io/?

  9. mac os 10.10下安装android studio问题:android studio was unable to find a valid jvm

    友情提示:小编在做到这一步前,已经确定jdk和环境变量已经安装并配置无误,关于怎么检查java环境变量请自行百度. 原因分析:android studio安装包下的info.plist配置文件中有个关 ...

  10. sql 字段字符串内容替换

    SELECT * FROM dbo.Table WHERE Name LIKE '%NYCL23%'UPDATE Table SET Name=replace(Name,'NYCL23','WYCL1 ...