2021.08.11 CMU DB 15-445: [Project1] buffer pool

buffer pool是有一个个page大小的内存块组成的,内存块的地址由*pages_与frame_id(偏移 or 索引)描述,内存块的数据结构由 Page 描述。
所以page和frame是一个概念?只是一个侧重地址计算,一个侧重数据结构。

buffer pool有几个辅助变量:

变量名 数据结构 功能
page_table 哈希表 记录哪些物理磁盘page_id是存在buffer中的,对应他们的frame_id(地址)
lru_replacer 双向链表 记录pin_count = 0的页地址,就是暂时不被使用的页
free_list 链表 记录page_id = INVALID_PAGE_ID的页地址,即没有对应物理磁盘页的空数据块地址

无论写哪个函数都要时刻维护 Page 结构与上面3个变量。

-----------------------------------------------------------------------------------------------------

Buffer_Pool_Manager

首先,所有在buffer_pool中的页/帧分为3种状态(参考blog):

0. 找内存中的可替换帧

这是一个通用操作,在FetchPage和NewPage中都会用到,先不着急后面会说到,这里只是讲一下步骤。

只是我的思路,可能比较拉,仅供参考

首先判断有没有可替换帧,就是通过free_list.empty()和replacer.size()来判断,如果没有可用的,直接返回false。
如果free_list有,就从中取一个。
如果free_list没有,就用replacer->Victim找一个frame,由于我写的策略是,在dirty页面要被覆盖(丢失)前,写回磁盘,有2个时刻会丢弃旧页面:1. victim交出已用过; 2. deletepage,所以在victim以后,这一帧可能是dirty的,即改写过,但还没有写回磁盘,要 diskwrite, 然后is_dirty = false。
然后由于这一帧内容即将被覆盖,那么原来的page_id也要从page_table_移除。

1. FetchPage
功能:数据库需要访问某个page,需要将page从disk加载到内存中。

首先要判断这个page是不是在buffer pool中,毕竟buffer pool的存在就是为了能快速复用暂时不用的页面,通过page_table_这个哈希表判断某个page_id在不在buffer中。如果在buffer中,那么这个page内容存在某个frame_id对应的地址中(通过pages_[frame_id]查询地址),此时又分为两种状态,也就是刚才说的: 1. 这个页正在被使用,此时pin++直接返回就行; 2. 这个页目前没被使用(pin = 0),但仍存在buffer里,那么就是在lru_replacer中了,所以要从replacer中移出来(replacer->pin),然后设 pin = 1。

如果不在buffer_pool中,就要在内存中腾出一块位置,装从disk读来的页,此时有两种策略:1. 从free_list中找一个帧(free的状态,可能是初始化以来就没有装,也有可能是deletepage后造成的空缺); 2. 用replacer找一个victim 装。用到前面0.找内存中的可替换帧的思路。最后,假设拿到了可用的内存块地址(frame_id&

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值