理解数据缓存
· 数据缓存是SGA的一部分,用于存放用户最近存取过的段的数据块的副本,这些段可能是数据段,索引段,簇段,LOB段,LOB索引段,回滚段,临时段,数据缓存单元的大小与数据库块大小一致。
· 数据缓存用下面的方法进行管理:
LRU列表
· 在Oracle执行SQL语句的过程中,相关的段数据要复制到SGA的数据缓存中来,这个操作由用户的服务器进程来执行;
· 与共享池类似,数据缓存也是由LRU算法来管理的,当数据缓存的缓存块被填满而又有新的缓存块请求时,LRU将最近最少使用的缓存块老化出去,而保留最近经常使用的缓存块,当一个用户发现要读取的数据块已在之前由其它用户读入时,就可以节约很多时间,因为从内存中读取比从磁盘中读取要快上数千倍;
· LRU算法管理一个LRU列表,这个列表类似于一个输送带,服务器进程将刚刚存取过的数据块放在输送带的开始端,随着更多的块被读入,先前读入的块向输送带末端移动,如果在到达末端之前某个块被再一次存取,则这个块又被移到开始端,否则就会从输送带末端跌落(缓存块被老化);
· LRU对全表扫描时读入缓存块的管理与上面的有些不同,这些块一读入就被放在LRU列表的末端,这样可以避免对大表全表扫描时把数据缓存中的所有缓存块都清洗出去;
· LRU算法管理下的缓存块有四种状态:
?nbsp; Free 自数据库启动以来尚未被使用过的缓存块;
?nbsp; Pinned 正在被服务器进程使用的缓存块;
?nbsp; Clean 曾被使用过且可立即被重用的缓存块,读入后未经修改或者最近一次修改已被写回磁盘,缓存版本与文件数据块一致;
?nbsp; Dirty 曾被使用过且不能立即被重用的缓存块,读入后作过修改且最近一次修改未被写回磁盘,缓存版本与文件数据块不一致;
· 管理脏块时会用到一个脏块列表(Dirty List,又名写列表),这个列表被检查点队列使用,用于跟踪所有的脏块,以第一次修改时间排序,脏块由DBW0进程写回磁盘。
用户服务器进程
· 当需要读取某个数据块时,服务器进程先到数据缓存中查看该块是否已存在,若没有找到,就需要将数据块从数据文件读到数据缓存中来,这首先要在数据缓存中找到一个可用的缓存块来容纳数据块的副本,这个过程中服务器进程可能要和LRU列表以及脏列表打交道:
?nbsp; 在LRU列表上查找可用块的时候,服务器进程将查到的脏块从LRU列表移到脏列表;
?nbsp; 随着脏块的加入,脏列表不断变长,当长度超过某个预定义的长度时,触发DBW0将脏列表上的脏块写回磁盘;
?nbsp; 如果服务器进程在LRU列表查找很多的块(超过某个阀值)都没能找到可用的块时,触发DBW0进程,将脏块直接从LRU列表写回磁盘。
· 如果服务器进程发现要找的块已在数据缓存中,但块的版本要晚于一致性读需要的版本时(版本更早时可直接使用),服务器进程在数据缓存中创建一个新块利用回滚段数据回滚到需要的版本(如果是在序列化事务中,且造成更晚版本的已提交的修改不是由当前事务造成的话,则报错)。
数据库写入进程(DBW0)
· DBW0进程负责将数据缓存中的脏块写回磁盘,这个操作在下面的情形下发生:
?nbsp; 服务器进程不断地将脏块从LRU列表移到脏列表,当脏列表的长度达到阀值时,DBW0将脏列表上的脏块写回磁盘;
?nbsp; 服务器进程在LRU列表上检查太多的块都没能找到一个可用块的时候,DBW0直接从LRU列上将脏块写回磁盘;
?nbsp; DBW0进程每三秒被激活一次,将LRU列表上的脏块移到脏列表,若脏列表长度达到阀值时,从脏列表上将脏块写回磁盘;
?nbsp; 检查点发生时,DBW0将脏块从LRU列表移到脏列表,再从脏列表写脏块回磁盘;
?nbsp; 数据库关闭时(不包括Shutdown Abort),DBW0将所有脏块写回磁盘;
?nbsp; 表空间热备前,DBW0将属于这个表空间的所有脏块从LRU列表移到脏列表,然后从脏列表将脏块写回磁盘;
?nbsp; 表空间离线时(Normal,Temporary),DBW0将属于这个表空间的所有脏块从LRU移到脏列表,然后从脏列表将脏块写回磁盘;
?nbsp; 删除段时,DBW0先将这个段的脏块写回磁盘
阅读(274) | 评论(0) | 转发(0) |