7.Oracle深度学习笔记——内存架构之SGA Buffer Cache
欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/50558162
Buffer cache是存储数据块的,数据库从数据文件中读取。一个buffer是缓存管理器暂时缓存当前或最近使用的数据块的内存地址。所有并发连接到数据库的用户可以共同访问buffer cache.
1. Buffer Cache的目的:
l 优化物理IO
l 让访问频繁的块保持在buffercache中,不用非常频繁的写块到磁盘
当数据库使能DatabaseSmart Flash Cache (flash cache)的时候,部分buffer cache可以保持在flash cache中。把buffers缓存在flash cache中要比从磁盘读快很多。
使用DB_FLASH_CACHE_FILE and DB_FLASH_CACHE_SIZE来配置多个flash 设备。
2. Buffer 状态
数据库使用内部算法来管理CACHE中固定缓存。一个BUFFER可以是下列任意状态:
n 未使用:缓存从未被使用或当前未被使用,这个类型数据库最容易使用
n 干净的:之前使用过,限制只包含读一致的块。不用做checkpoint.数据库可以pin住block然后再使用。
n 脏的:包含修改过的数据,未写到磁盘,数据库在使用前必须checkpoint.
每个buffer有一个访问模式:pinned或free(unpinned). 一个pinned 的buffer,当一个会话访问的时候不会从内存中老化出来。多个会话不同同时修改一个pinned 的buffer.
3. Buffer模式
当客户端请求数据时候,ORACLE通过一下模式从数据库buffercache中获取buffer.
3.1 当前模式
当前模式获取,也叫作db blockget.从缓存中直接获取一个块。例如,一个未提交的交易更新了块中固定两行,当前模式后去,直接从块中获取这些未提交的行。
3.2 一致性模式
一直读获取是后去一个读一致的块。可能使用UNDO数据。例如,一个未提交的交易更新了块中的两个,如果不同会话请求修改过的块,那么数据库使用UNDO 数据来创建一个读一致块(不包括未提交更新)。
4. Buffer I/O
逻辑IO,就是我们所说的bufferIO. 当请求的buffer没有在内存中找到时,数据库会进行物理IO将BUFFER从磁盘或FLASH 中读到内存中,然后再用给一个逻辑IO来读缓存的BUFFER。
4.1 Buffer替换算法
为保证buffer访问的高效,数据库必须绝对哪些buffer缓存在内存,哪些从磁盘获取。数据使用给如下算法:
4.1.1 块级基于LRU 替换算法
至少一个LRU列,包含指针指向脏的和干净的BUFFERS。 LRU有一个热端和冷段。冷 BUFFER表示最近为使用的,热BUFFER表示经常访问,最近也被访问的。概念上,只有一个LRU,但是为了数据并发,数据库经常使用多个LRU列表。
4.1.2 对象级基于热度 替换算法
从12.1.0.2开始,自动大表缓存特性使得,表扫描在以下场景可以使用不同的算法。
并行查询:在单实例和RAC下,当DB_BIG_TABLE_CACHE_PERCENT_TARGET初始化为非0 ,PARALLEL_DEGREE_POLICY设置为AUTO或adaptive的时候,并行查询可以使用大表CACHE。
串行查询:只在单实例配置,当DB_BIG_TABLE_CACHE_PERCENT_TARGET初始化为非0串行查询可以使用大表CACHE。
当表不能放到内存时候,数据库基于访问模式来决定哪些BUFFER来缓存。
例如,如果表只有95%在内存,那么数据库选择5%的块留在磁盘而不是读到内次再写到磁盘,这样会引起抖动。当CACHE多个大对象时候,数据库考虑将热的表变得更热,将冷的表变的更冷,这样影响到哪个块被CACHE。
初始化参数DB_BIG_TABLE_CACHE_PERCENT_TARGET设置这个算法BUFFER CACHE的百分比
4.2 Buffer写
数据库写进程周期性写冷、脏BUFFER到磁盘。DBW在以下环境下写BUFFERS。
l 服务进程不能找到干净的缓存来将行块读入到数据库的BUFFER CACHE中
如果BUFFER是脏的,空闲的BUFFER数量下降。如果数量下降到一个阈值,然后需要干净的BUFFER,那么服务进程会通知DBW来写。
l 数据库必须提前checkpoint,CHECKPOINT是REDO进程实例恢复的开始
l 表空间改变为只读或下线
4.3 Buffer读
当干净或未使用的BUFFER数量低的时候,数据库必须从BUFFERCACHE中移除。算法取决于FLASH CACHE是否使能。
如果FLASH CACHEDISABLED
数据库根据需要重新使用干净的BUFFER,并覆盖。如果覆盖的BUFFER后续又需要,那从磁盘中读取。
如果FLASH CACHE ENABLED
DBW将干净的BUFFER 写到FLASH CACEH中,使能重新使用内存中的BUFFER。数据库将BUFFERHEADER保存在LRU列表,可以定位到FLASH CACHE中的BUFFER BODY。如果后续被需要,那么可以直接从FLASH CACHE中读取,而不是从磁盘中读取。
4.4 Buffer Touch次数
数据库使用TOUCHCOUNT来记录LRU列表上BUFFER被访问的频率。这个机制使得数据库在BUFFER 被PIN住的时候增加计数,而不是经常的从LRU列表上移除。
PS:数据库不会经常物理移动块,只是在列表上改变指针的位置。
当BUFFER被PIN住的时候,数据库会决定TOUCHCOUNT是不是上次增加的。如果是3秒之前,那么继续增加,如果在3秒内增加过,那么不再增加。防止BUFFER的计算爆发增长。例如插入多个行到一个数据块,数据块会将这些插入视为一个TOUCH。
如果BUFFER在LRU的冷端,但是TOUCHCOUNT很高,那么BUFFER会移动到热段。如果TOUCH COUNT很低,那么BUFFER 从CACHE中老化出去。
5. Buffer Pools
Buffer pool是一个buffer的集合。数据块的BUFFERCAHCHE 分成一个或多个BUFFER POOLS,以同样的方式管理块。POOL老化或缓存块没有根本的区别。
可以手动配置不同BUFFERPOOL。
可以指定特定的对象到合适的BUFFERPOOL。
这样可以隔离段到热、温、冷的BUFFER POOLS
如下:
l DEFAULT POOL
通常缓存的地方。Default pool一个BUFFER POOL。其他POOL的配置对DEFAULTPOOL没有影响。
从12.1.0.2开始,BIG TABLECACHE是DEFAULT POOL的可选项,使用基于问题,对象级别的替换算法。
l KEEP POOL
KEEP POOL 是给哪些访问频繁,但是因为空间为题不得不老化离开DEFAULT POOL的块。
KEEP POOL的目标是保留对象在内存,避免IO操作。
l RECYCLE POOL
用于哪些使用不频繁的块。防止浪费CACHE中不必要的空间。
6. Buffer和全表扫描
数据库使用复杂的算法来管理表扫描。默认,将缓存插入到LRU列表的中间,避免热块换出。
如果全表扫描,需要将表中高水位下所有行读取。如果大小超过BUFFER CACHE大小,一次全表扫描会清除所有BUFFER CHACHE。
l 默认全表扫描方式
如果是小表,则加载到内存。
如果是中表,一个算法更具上一次表扫描的之间,BUFFER的老化时间和BUFFER CACHE中的空间来决定。
如果是大表,数据库典型的使用直接路径读。这样绕过SGA,直接读到PGA。对于中表,也可能使用直接读。
从12.1.0.2开始,数据库自动计算内存SGA是否足以存放整个数据库,以及CACHEING 表访问是否性能受益。如果达标,那么很多其他内部标准也会部分,ORACLE对待所有表就是小表。当然数据库不会缓存标记为NOCACHE的 LOBs
l 并行查询执行
当数据库有很大内存时候,数据库缓存并行查询数据,而不是使用直接读方式。典型的,并行查询一般在低并发的数据仓库中。
l CACHE属性
在极少情况下,我们不需要缓存。所以可以指定altertable … cache来将大表读取到BUFFER CACHE中。这样数据库会空出BUFFER CACHE来读取表。当然使用这个要小心,因为会清除CACHE中大量的其他块。
l KEEP属性
对于大表,可以使用ALTER TABLE …STORAGE BUFFER_POOL KEEP来让块加载到KEEP POOL中。
l 强制全表缓存模式
在一些场景下,可以显示的使用ALTERDATABASE … FORCE FULL DATABASE CACHING语句来强制缓存整个数据库。这个模式在12.1.0.2上可用。
Oracle建议只有在BUFFERCACHE的大小远比数据库大小大的时候,可以使用。这个建议适合于单实例和RAC。