Oracle执行查询时如何判定哪些数据块不在buffer cache中需从磁盘读取
Oracle判定数据块是否需要从磁盘读取的实现逻辑
我们讨论的前置执行场景如下:
第一条查询:
select * from employees where salary > 10000;
间隔一段时间后执行第二条查询:
select * from employees where salary > 500;
第二条查询覆盖的表数据范围更大,需要访问更多数据块,Oracle通过以下逻辑判断哪些块需要从磁盘读取:
- 每个Oracle数据块都有全局唯一的标识DBA(数据块地址,Data Block Address),DBA记录了该块所属的数据文件编号和块在文件内的偏移编号,只要是同一个数据块,DBA是固定不变的。
- Oracle的Buffer Cache(数据缓冲区)中维护了Buffer Cache哈希表,该哈希表以DBA为键值构建,每个哈希桶下挂载对应哈希值的缓冲区头(Buffer Header)链表,每个缓冲区头对应Buffer Cache里一个实际缓存的数据块,头信息里记录了对应块的DBA、缓存状态、使用计数、是否为脏块等核心元数据。
- 第二条查询执行时,执行计划会先梳理出本次需要扫描的所有数据块对应的DBA列表:
- 对每一个待访问的DBA,Oracle会先计算该DBA的哈希值,定位到Buffer Cache哈希表中对应的哈希桶
- 遍历该哈希桶下的缓冲区头链表,查找是否存在DBA匹配、且状态为有效的缓冲区头条目
- 如果能找到匹配的有效条目,说明该数据块已经缓存在Buffer Cache中,直接访问缓存即可,不需要读取磁盘
- 如果找不到匹配条目,或者匹配的条目已经被标记为无效(已经被淘汰复用给其他数据块),说明该块不在有效缓存中,需要触发磁盘IO读取对应块,加载到Buffer Cache后再更新对应的哈希表条目
- 为了保证并发场景下哈希表查找的一致性,整个查找过程会持有对应哈希桶的Cache Latch(缓存闩锁),避免查找过程中哈希表结构被其他进程修改。
内容的提问来源于stack exchange,提问作者oramas
相关产品推荐
相关产品推荐

