CMU15445 Lecture 5 Buffer Pools


本节主要介绍DBMS是如何管理memory与disk之间的数据来回移动的

为什么需要Buffer Pools

由于系统不能直接处理磁盘中的数据,DBMS需要为了系统将数据从磁盘放入内存中,又由于内存容量有限,DBMS需要进行内存数据与磁盘数据的交换;这其中的权衡是,需要系统看起来好像所有的数据都以及在内存之中,这需要DBMS考量空间的控制与时间的控制

  • 空间控制
    目标是使得常常需要被使用的page尽可能保存在内存中
  • 时间控制
    目标是,使得在磁盘与内存中交换数据的停顿最小化

锁与闩(locks & latches)

  • 锁(lock)
    锁是一个高层面,逻辑原语,用来在事务之间,保护数据库的内容(诸如tuple,table,database);事务会全程维护一个lock;在查询执行时,database系统可以告诉用户现在持有了什么锁;lock可以回滚,也就是rollback changes
  • 闩(latch)
    闩是一个低层面的保护原语,用来保护DBMS的关键区域的内部数据结构(hash table, region of memory);一个区别是latch只有在操作(比如query)执行的时候才会持有,另外一个区别是latch不能够回滚,也就是不能rollback changes

Buffer Pool能够做什么

buffer bool 开辟于内存里,可以看作是磁盘页在内存中的对于database的缓存,buffer pool的单位容量被称为frame

Buffer Pool的元数据

  • page table
    page table 是buffer pool维护在内存中的元数据,它保存着page_id与frame_id(也就是buffer pool中frame的位置)的映射;这个间接层(indirection layer)使得buffer pool中页可以不按顺序存储;这里需要区别page directory与page table,前者是保存这page_id与数据库文件位置的映射
  • dirty flag与pin/reference counter
    如果一个page在内存中被修改,page table中会对page置位dirty标志,这样在将该page换出时,就需要将该页写入磁盘
    对于某个page,可以用pin/reference Counter追踪有多少线程在访问该页,只要其不为0,那么storage manager不能够将该page驱逐出内存

内存分配策略

需要分配多少内存给buffer pool又两种考量

  • global policies
    DBMS需要考虑全局负载,也就是需要考虑所有的当前正在执行的事务,以此来找到一个最优的分配给buffer pool的大小
  • local policies
    只考虑一个query或transaction,为了使得它运行的更快,即使其不是全局最优

Buffer Pool的优化

多缓冲池(Multiple Buffer Pools)

DBMS可以基于不同的目的维持多个缓冲池(比如每个数据库一个缓冲池,每种页类型一个缓冲池),这样一来,每个buffer pool可以采用定制化的local police,一个最大的好处时可以减少latch的竞争与提高局部性
如果又多个buffer pool,如何区分pages,并放到给定的buffer pool中呢,有两种方案:

  • Object IDs
    给每个page添加一个新的属性,Object id
  • hashing
    对于page_id进行hash,以决定buffer pool

预取

DBMS可以基于query方案进行pre-fetching优化;这个策略常用于线性访问

scan sharing

区别与result caching,result caching是指第一个query查完数据,那么将其缓存下来;而scan sharing是指,当两个查询query的数据需要扫描同一个个page序列,那么它们的cursor合并为一个

但是对于LIMIT子句的出现,可能会导致错误

buffer pool旁路

buffer pool bypass,对于某些需要线性读取大量数据的query,可以不将数据缓存在buffer pool,这样就可以随意丢弃,减少开销;另外对于诸如(sorting, joins)中间数据,可以不放在buffer pool

OS Page Cache

磁盘操作也会通过OS API被缓存,除非OS被告知不要去维护缓存。但是一般DBMS会绕过OS取进行磁盘操作,这样一来可以减少缓存的冗余,并且DBMS可以执行自己的evict policies
但是也有例外,Postgres就不绕过OS

buffer pool replacement policies

替换策略需要考量正确,精准,速度与元数据开销

  • LRU(Least Recently Used)
    基于时间戳的LRU
  • CLOCK(LRU的近似算法但更简洁)

  • 其他
    对于sequential flooding,前两者都无济于事,有三种解决方案:
    • LRU-K,以前k次的page的访问来推测出之后该page被访问的概率有多大
    • locllization, 基于每个query与transaction做eviction
    • priority hints,对于每个page添加优先级属性,基于每个query的上下文

脏页驱逐

对于未置位dirty bit的page,在evict时,可以直接丢弃;但是置位了dirty bit 的page,为了保持一致性,需要将其写回disk,这里存在着一种权衡,立马驱逐还是说保存在内存中,以防止未来它还需要被读

  • background writing
    周期性集中异步刷脏,据说可以解决the problem of having to write out pages unnecessarily

OTHER MEMORY POOLS

参考

note5
b站视频