首页 > 数据库 > Oracle > BUFFER CACHE
数据缓存区的目的是减少磁盘IO的数量,因为数据是驻留在磁盘上,而我们在访问处理数据的时候,需要将被经常性访问的数据缓存在内存中,因为访问内存要远比访问磁盘快的多,但是数据缓存区是有限的,不可能所有的数据都放到这里面,这就要求数据库能够使用一种算法优化,来确定那些数据能够长时间放置在数据缓存区中,那些就要抛出出缺。
数据缓存区的使用有以下的好处:
1、 能够提供更加快速的访问数据库块的一种访问方式。
2、 提供了一种处理同步块的改变请求的策略。
3、 保存数据库块的一致读的多版本(多版本一致性)。
4、 通过内部的结构维护数据缓存。
基础的概念:
Hash buckets是一个结构,维护这数据缓存头的列表,是有相关的rdba和类号来分类;
Hash chain是在一个hash bucket上的一个数据缓存头的列表。
LRU:是一种机制,用于确定在搜索空闲的缓存的时候,哪一个缓存能够被使用。
缺省的hash bucket数目是:DB_BLOCK_BUFFERS*2
通过设置参数_DB_BLOCK_HASH_BUCKETS能够重写hash bucket数目
每一个HASH BUCKET包含这一个缓存头的一个链,
每一个hash bucket有一个cache buffers chains latch来保护对这个链的同步访问。
这几个概念说这相对比较复杂,解释一下,这里还有一个缓存内存区域,这个是存放数据的物理位置,在上面有几个结构:
Hash bucket
Buffer header
其中Hash bucket的数目是通过参数设置的,之所以使用这个概念,主要是才查找缓存的数据的时候能够更快找到所需要的数据的地址。而在Hash bucket这个结构中有一个链,这个链是有Buffer header组成,在Buffer header这个结构上有指向存放数据具体位置的指针地址。在查找数据的时候,数据库通过hash算法确定是有哪一个Hash bucket来存放所需要的Buffer header,在通过Buffer header上的buffer address来确定具体数据存放的位置。
还有两个链,LRU和LRUW,这两个链也是通过Buffer header上的LRU chain的指针来实现的,每一个Buffer header只有一个LRU chain指针,这也就是为什么同一个块不能同时存放在LRU和LRUW的原因了。
在这里我们可以看到,这里组成了一个二维的一个网状的一个链网,这个联网相互交叉,在LRU和LRUW其实只是一个虚拟的一个链,是有Buffer header来实现,Hash bucket目的是实现数据地址的快速查找,但是LRU和LRUW是找到相应的各自的功能,Oracle就是通过这样的设计来实现一种物理结构实现两种不同的功能。
缓存池有三种:
缺省
Keep
Recycle
用法:
将大的数据段放置在recycle缓存中,将小的,经常使用的段放置在keep池中。
可以通过查看以下的视图来查看段级的统计(oracle9i2)
-v$segstat_name
-v$segstat
-v$segment_statistics
LRU:
通常LRU是有两个列表组成:
LRUW(LRU写列表,也称为葬列表),是为了维护当前脏的缓存。LRU就维护剩下的缓存了。
使用初始化参数DB_BLOCK_LRU_LATCHES来设置多LRU列表,这个参数只是用于多CPU机器上。每一个LRU列表是由一个cache buffers lru chain latch来进行保护。
每一个LRU是有一个LRU和LRUW组成,被称为working set。缓存是通过一种循环机制来指定working set的。在使用working set的时候,进程将尝试所有的latch直到找到一个请求的LRU latch。在多DBWR进程的情况下,每一个DBWR将管理各自的LRU集。
配置多DBWR是通过设置参数 DB_WRITE_PROCESSES来实现。
缺省的working set数目是有DBWRs×缓存池的最大数目确定的,这些latch能够在每一个池的working set中间分布。
使用缓存的用户:
数据块读是有一个前台的Oracle进程来实现的,这个进程读数据块到缓存中然后做标志来改变,也就是说,在从磁盘中读取数据块是由Oracle的服务器进程来进行操作的,和用户进程无关,也就是说这一部分是由Oracle自己来进行管理的。
而数据块写则是由后台Oracle进程(DBWR)来实现的。DMWR进程将已经被修改的数据块写入到磁盘中。
获取当前数据的步骤
1、 通过所要查找的RDBA地址,通过hash算法,得到一个hash值,而这个hash值是和hash bucket相对应,而每一个hash bucket后面连接一个hash链,然后在通过扫描这个hash链来找到相应的地址。
2、 在链上查找可以使用的缓存或者从磁盘上读。
在链上查找有以下的原则:
n 忽略和RDBA不相匹配的缓存块
n 等待reading buffer,然后返回
n 跳过CR(一致性读)的buffer
n 如果CUR(当前)buffer被一个兼容的模式把持着,就使用
n 如果所有的其他用户是CR状态,
n 如果在缓存中没有这个buffer,则从磁盘中读取
3、 将状态对象附加在缓存头上。
4、 返回数据存放区域的指针。
这里介绍的是如何从一个RDBA地址上找到当前数据缓存的位置。
Buffer管理
Buffer被hash是初始化到LRU-AUX列表上
写的优先级
写的优先级被分成三种:高,中,低
每一个写操作被赋予一个优先级:
Type of Write | Priority |
Tablespace checkpoints | Low |
User initiated checkpoints | Low |
Cold dirty buffers (aging) | Medium |
Incremental checkpoints | Medium |
Media recovery checkpoints | Medium |
Instance recovery checkpoints | High |
Thread CKPT | High |
Ping | High |
Working set和DBWR
DBWR进程工作在指定的Working set,Working set工作是在一个循环机制上运行的。
DBWR进程写的几个原因:
n 需要空闲的空间
n Checkpoint
n Ping写
n 清除不常用的脏buffer
在Oracle8i之前,DBWR是由于超时或者由于前台调用才会被初始化,而且每一种是有不同的类型的。而在此之后,所有的请求都所是有单一的请求来实现。
DBWR是由前台进程调用,用于清除脏的buffer,扫描的深度
Checkpoint是用于保证记录在日值中的所有的数据块都被写入到磁盘中。检测点的结构:
Checkpoint SCN
Checkpoint RBA
分配给checkpoint的线程
Timestamp
线程位图使能
检测点和文件队列
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/222350/viewspace-907892/ ,如需转载,请注明出处,否则将追究法律责任。