Oracle是一个充分利用内存技术、缓存技术来解决数据库操作问题的DBMS。同外存储器(硬盘存储)相比,内存虽然具有断电遗失的问题,但是处理速度上却有显而易见优势。
Oracle早期进行的架构设计中,就充分体现出缓存Cache的广泛应用。目前Oracle的核心技术,如Undo/Redo、Share Pool和Buffer Cache,都是建立在缓存数据重用的基础之上。而作为数据库Instance关键组件的SGA,就是一块共享内存组织。
1、从Buffer Cache中的缓存block谈起
Buffer Cache是Oracle SGA的一块重要区域。其中的内容就是所有Server Process读出的数据块。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
在Oracle中,当一个Server Process需要进行数据读写的时候,通常的行为并不是直接到物理存储上进行物理IO读写。Server Process首先会在buffer cache中寻找需要的数据块之前有没有被缓存到其中,如果有的话,就直接操作数据块(我们称作发生一次Logical Read)。如果Server Process没有在Buffer Cache中找到对应数据块的话,才会启动物理存储设备的读写操作,将需要的数据块读取出来(我们称作发生一次Physical Read)。
对操作完的数据块,Oracle并不是直接就将其释放掉,而是缓存在Buffer Cache中一段时间。这里Oracle的出发点是这样:如果这个数据块现在使用过,那么之后也需要的概率就会很高。那么,该数据块留在buffer cache中,下次使用的时候就可以避免一次Physical Read,用于提高性能。
通过buffer cache机制,Oracle加快了数据访问的速度,大大缓解了由于物理IO而带来的性能问题。
但是,buffer cache的引入还带来了管理复杂性。数据块缓存在buffer cache中,需要进行快速的检索和管理,同时伴随着生命周期管理。其中,常常被我们提及的就是数据块的“age out”机制:数据块什么时候会剔除出buffer cache。
在Age Out的问题上,Oracle使用的是基于LRU(Least Recent Use)算法和数据链。Buffer cache本质上是一系列的数据链表,分别根据数据块使用的频度和时间分布在两端,一端为经常使用、“热度较高”的MRU端,而另一端则是使用频度较低的数据块。当buffer cache中空闲空间不足,或者其他引发条件发生时,Oracle就会将LRU端的数据块清除出缓存。
2、“Who should be aged out !”
相对于整个数据库,SGA中的buffer cache总是相对较小的。总是有数据块会被age out出去。那么,这种机制有什么问题呢?
如果一个数据块经常被访问,那么肯定会驻留在LRU列表的MRU端,这样被age out出去的几率较低。这种情况也就是可以最大限度的利用cache的优势,减少物理IO的发生。
但是,如果一个系统中,buffer cache相对较小,而操作SQL进行IO读取量又比较大。那么,即使经常使用的数据块,也是存在会被频繁age out,但又频繁cache入内存。这样,系统的IO性能会形成负载。
上面的情况在实际中是很典型的。有的时候,我们会以高频繁度访问一些数据表,访问的数据相似。这种情况最好的处理方式是在应用前端建立数据缓存,直接减少SQL交互次数。但是实际中,我们却经常发现该部分数据频繁的物理IO。
还有一些情况也值得关注,就是不同类型的数据块在buffer cache中可能存在优先级差异。例如,索引块比数据块在buffer cache中保留的几率要高,因为Oracle认为索引块的作用要比普通的数据块大得多。还有,如果数据块是通过全表扫描(Full Table Scan)读取进buffer cache,那么Oracle认为这个数据块只是暂时的被使用,很快就会被age out出去。
上面的一些问题告诉我们:在统一的buffer cache管理下,一些特殊情况是不能够忽视的。我们需要建立一种机制,来进行细致化的cache管理。于是,Oracle对Buffer Cache使用了Keep和Recycle两个特殊管理空间。
3、Keep池和Recycle池
Oracle将Buffer Cache划分为三个子池,分别为Default、Keep和Recycle。在三个子池中,Oracle对不同缓存优先级别数据块进行分别管理,力图维持不同的缓存策略。
Default、Keep和Recycle三个子池会共享Buffer Cache大小。在Oracle10g和11g时代,广泛应用自动内存调整技术(ASMM),这部分空间在参数文件设置中是为空的。
SQL> show parameter buffer;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
buffer_pool_keep string
buffer_pool_recycle string
db_block_buffers integer 0
--10g以上版本应用
SQL> show parameter cache_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
(篇幅原因,有省略…)
db_cache_size big integer 0
db_keep_cache_size big integer 0
db_recycle_cache_size big integer 0
当我们启动数据库实例后,Oracle会根据参数文件和最后一次启动的配置数值,进行内存SGA空间分配。
SQL> select * from v$sgastat where pool is null;
POOL NAME BYTES
------------ -------------------------- ----------
fixed_sga 1336904
buffer_cache 79691776
log_buffer 6111232
Keep池就是在buffer cache中的一块区域。如果我们希望数据表或者其他对象长期的保留在内存buffer cache中,不会轻易的被age out出去,就可以设置在Keep池中。设置在Keep池中的对象,和Default池对象相同,都是通过LRU算法维持在LRU列表中。放置在Keep池中对象,拥有单独的LRU列表,不会被其他低优先级数据表“排挤”出内存空间的。
而Recycle池道理与Keep池相同。如果一些数据对象体积很大,但是访问机率较低,我们希望尽快被age out出去,就可以将其放置在recycle中。这样,独立的recycle LRU列就会将该部分的数据块单独维护,并且尽快的age out出去。
对Keep和Recycle池,有两个方面问题需要关注:
首先,默认情况下,数据段对象的缓存是在Default池中的。只有在特殊的系统、业务需求下,我们处于优化的目的,才会考虑启用Keep池和Default池。
SQL> select component, current_size, min_size, max_size from v$sga_dynamic_components where component in ('DEFAULT buffer cache','KEEP buffer cache','RECYCLE buffer cache');
COMPONENT CURRENT_SIZE MIN_SIZE MAX_SIZE
------------------------------ ------------ ---------- ----------
DEFAULT buffer cache 83886080 79691776 0
KEEP buffer cache 0 0 0
RECYCLE buffer cache 0 0 0
其次,所谓Keep池和Recycle池,其中差异是分类类型的差异。针对不同的类型数据,在Keep、Recycle和Default池中,都是采用相同的LRU算法,都是存在Age Out机制。例如,如果Keep池设置较小,而我们设置的Keep住对象较大,同样会有Keep池的对象被Age Out出去。
下面,我们来看一下如何定义数据表在Keep和Recycle池中,以及相应的效果。
4、子池对象定义和特性——Default池
默认情况下,数据表等对象是定义在Default池中的。
SQL> create table t_def as select * from dba_objects;
Table created
SQL> col segment_name for a20;
SQL> select segment_name,BUFFER_POOL from dba_segments where segment_name='T_DEF';
SEGMENT_NAME BUFFER_POOL
-------------------- -----------
T_DEF DEFAULT
SQL> select table_name, cache from dba_tables where table_name='T_DEF';
TABLE_NAME CACHE
------------------------------ ----------
T_DEF N
默认情况下,我们的数据表是定义在Default池中。那么,我们在使用时,数据表对应块是放置在default池。
SQL> set timing on;
SQL> set autotrace traceonly;
SQL> select count(*) from t_def;
已用时间: 00: 00: 00.49
统计信息
----------------------------------------------------------
28 recursive calls
0 db block gets
770 consistent gets
692 physical reads
0 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select count(*) from t_def;
已用时间: 00: 00: 00.03
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
697 consistent gets
0 physical reads
0 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
--之后进行一系列的数据操作,不涉及数据表T_DEF。再次执行该语句。
SQL> select count(*) from t_def;
已用时间: 00: 00: 00.58
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
697 consistent gets
377 physical reads
0 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
上面典型是一个Default池处理场景。一共执行了三次语句,执行时间分别为0.49s、0.03s和0.58s。体现出default LRU链工作的特点。
当第一次执行的时候,Oracle Server Process从Buffer Cache中不能够获取到全部的数据表T_DEF块。于是进行692次的物理IO和770次逻辑IO,返回结果,同时将数据块缓存在Default池的LRU链上。
第二次执行的时候,由于两次间隔短且没有额外IO操作,所以Server Process直接在Buffer Cache中找到了需要的数据块。该次操作就不需要进行物理IO,只有697次逻辑IO。执行时间也因为纯内存操作而减少到0.03s。
最后一次操作前,系统进行了一系列的数据块操作,有部分的Default数据表块被age out出去。该次的操作伴随着一定的物理IO操作,执行时间也有所增加。
下面我们看Keep池和Recycle池的使用。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/17203031/viewspace-714717/ ,如需转载,请注明出处,否则将追究法律责任。