CMU15-445-Spring-2023-Project #1 - Buffer Pool

前置知识,参考上一篇博客:CMU15-445-Spring-2023-Project #1 - 前置知识(lec01-06)

在存储管理器中实现缓冲池。缓冲池负责将物理页从主内存来回移动到磁盘。它允许 DBMS 支持大于系统可用内存量的数据库。缓冲池的操作对系统中的其他部分是透明的。例如,系统使用page唯一标识符(page_id_t)向缓冲池请求一个页面,但系统并不知道该页面是否已在内存中,也不知道系统是否需要从磁盘中获取该页面。
实现必须是线程安全的。

Task #1 - LRU-K Replacement Policy

这部分负责追踪缓冲池中的页面使用。
Impl
src/include/buffer/lru_k_replacer.h
src/buffer/lru_k_replacer.cpp

LRU-K算法的基本思想是维护一个大小为K的历史记录,记录最近K次访问的信息。当需要替换缓存中的数据时,LRU-K会根据这个历史记录来判断哪些数据是最近最少使用的,然后将其替换出去。

与LRU相比,LRU-K增加了对历史访问的考量,因此更加灵活,能够更好地适应不同访问模式下的缓存需求。
LRU-K 算法驱逐的帧的后向 k 距离是替换器中所有帧的最大值。后向 k 距离计算为**当前时间戳(指当前时间而不是history中最近时间戳)**与前第 k 次访问时间戳之间的时间差。历史访问次数少于 k 次的帧的后向 k 距离为 +inf。当多个帧的后向 k 距离为 +inf 时,替换者会驱逐history中最末时间戳最小的帧。

  • Evict(frame_id_t* frame_id):驱逐与所有其他可驱逐帧相比后向 k-distance 最大的帧。在输出参数中存储帧 ID 并返回 True。如果没有可驱逐帧,则返回 False。驱逐不同于remove,区别在于只需要将is_evictable_置为false即可。
  • RecordAccess(frame_id_t frame_id):记录给定帧 ID 在当前时间戳被访问,没有存储该帧则新建一个node,此方法应在页面被固定在 BufferPoolManager 中后调用。
  • Remove(frame_id_t frame_id):清除指定帧的所有访问历史记录,并从node_store_中删除。只有在 BufferPoolManager 中删除页面时才调用此方法。
  • SetEvictable(frame_id_t frame_id, bool set_evictable):该方法控制帧是否可驱逐。它还控制 LRUKReplacer 的大小。具体来说,当某个页面的引用计数达到 0 时(pageGuard进行drop->bpm进行unpin),其对应的帧就会被标记为可驱逐,替换器的大小也会随之增加。
  • Size():该方法返回当前 LRUKReplacer 中可驱逐帧的数量。

Task #2 - Buffer Pool Manager

实现缓冲池管理器(BufferPoolManager)。BufferPoolManager 负责从 DiskManager 抓取数据库页面并将其存储到内存中。BufferPoolManager 还可以在收到明确指示或需要删除页面以便为新页面腾出空间时,将脏页面写出到磁盘。

系统中的所有内存页面都由 Page 对象表示。缓冲池管理器无需了解这些页面的内容。Page 对象只是缓冲池中内存的容器,也就是说,每个页面对象都包含一个内存块,DiskManager 将把它用作从磁盘读取物理页面内容的复制位置。缓冲池管理器(BufferPoolManager)会重复使用同一个页面对象来存储数据,因为数据会在磁盘上来回移动。这意味着,在系统的整个生命周期中,同一个页面对象可能包含不同的物理页面。页面对象的标识符(page_id)可追踪其包含的物理页面;如果页面对象不包含物理页面,则其 page_id 必须设置为 INVALID_PAGE_ID。

每个页面对象还维护一个计数器(pincount),用于记录 “固定” 该页面的线程数。缓冲池管理器不允许释放被钉住的页面。每个页面对象也会记录它是否变脏(write过)。需要记录页面在解除固定前是否被修改过。BufferPoolManager 必须先将脏页面的内容写回磁盘,然后才能重新使用该对象。

BufferPoolManager 实现将使用 LRUKReplacer 类。LRUKReplacer 将跟踪页面对象被访问的时间,以便在必须释放帧以腾出空间从磁盘复制新的物理页面时,决定驱逐哪个页面对象。在 BufferPoolManager 中将 page_id 映射到 frame_id 时,请再次注意 STL 容器不是线程安全的。
Impl
src/include/buffer/buffer_pool_manager.h
src/buffer/buffer_pool_manager.cpp

  • FetchPage(page_id_t page_id):从缓冲池中获取指定page,此时增加pincount,且无法被驱逐;如果page不在缓冲池中,从空闲列表或替换器中选择一个frame(总是先从空闲列表中查找),通过调用 disk_manager_->ReadPage() 从磁盘读取页面,然后替换frame中的旧页面。如果空闲列表中没有可用页面,且所有其他页面当前都被固定(evictable),则应返回 nullptr。如果旧页面is dirty,需要先写入磁盘。
  • UnpinPage(page_id_t page_id, bool is_dirty):is_dirty 参数会跟踪页面在固定期间是否被修改,如果页面之前is_dirty就为true,但是还没有写入磁盘,也就是脏页面会被缓冲,不会立即写回,避免下次fetch又要从磁盘读出。这时就不能置为false。如果pincount减为0了,需要将驱逐标记设为true。
  • FlushPage(page_id_t page_id):刷新页面,将页面写入磁盘,而不管其固定状态如何。
  • NewPage(page_id_t* page_id):在缓冲池中创建一个新的page,AllocatePage() 私有方法会为 BufferPoolManager 提供一个唯一的新页面 ID。
  • DeletePage(page_id_t page_id):删除缓冲池中的指定page,DeallocatePage() 方法是一个无操作的方法,它模仿释放磁盘上的页面。
  • FlushAllPages()

DiskManager::WritePage() 函数需要在获取的页面为脏时,或者刷新页面时调用。不要忘记unset页面的is dirty标记。

Task #3 - Read/Write Page Guards

在缓冲池管理器中,FetchPage 和 NewPage 函数返回的指针指向已被钉住的页面。钉住机制确保在页面上没有更多读写之前,页面不会被驱逐。要表明内存中不再需要该页面,必须手动调用 UnpinPage。

实现用于存储 BufferPoolManager 和 Page 对象指针的 BasicPageGuard。页面防护确保一旦相应的页面对象退出作用域(析构),就会调用 UnpinPage。

由于 BasicPageGuard 隐藏了底层的页面指针,因此它还可以提供 read-only/write API,这些 API 可提供编译时检查,以确保为每个用例正确设置 is_dirty 标志。

在未来的项目中,多个线程将读写同一页面,因此需要读写器锁存来确保数据的正确性。请注意,在页面类中,有相关的锁定方法用于此目的。与取消页面锁定类似,在使用页面后可能会忘记取消锁定。为了缓解这一问题,将实现 ReadPageGuard 和 WritePageGuard,一旦页面超出范围,它们就会自动解除锁定。

Impl
src/storage/page/page_guard.cpp
src/buffer/buffer_pool_manager.cpp

实验结果

优化方面,减少stl的使用会明显增加qps。
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/602870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用的窗体控件

常用窗体控件 MenuStrip:一个标准的菜单栏控件,可以添加菜单单项和子菜单项 //双击子菜单项同样可以添加点击事件 //menu:菜单 item:菜单选项 //当点击新建选项的时候触发的事件 private void 新建ToolStripMenuItem_Click(ob…

QT+OSG/osgEarth编译之五十八:OpenEXRUtil+Qt编译(一套代码、一套框架,跨平台编译,版本:OpenEXRUtil-3.2.1)

Qt+OSG/osgEarth跨平台编译(用Qt Creator组装各个库,实现一套代码、一套框架,跨平台编译)_qt + osgearth安装-CSDN博客 目录 1、OpenEXRUtil介绍 2、文件下载 3、文件分析

【论文解读】基于神经辐射场NeRF的像素级交互式编辑(Seal-3D)

来源:投稿 作者:橡皮 编辑:学姐 论文链接:https://arxiv.org/pdf/2307.15131 项目主页:https://windingwind.github.io/seal-3d/ 摘要: 随着隐式神经表征或神经辐射场(NeRF)的普及…

ElecardStreamEye使用教程(视频质量分析工具、视频分析)

文章目录 Elecard StreamEye 使用教程安装与设置下载安装 界面导航主菜单视频窗口分析窗口 文件操作打开视频文件 视频流分析帧类型识别码率分析分析报告 高级功能视觉表示比较模式自动化脚本 下载地址1:https://www.onlinedown.net/soft/58792.htm 下载地址2&…

Typora 编辑器 讲解 包括使用方式 快捷键 附带下载地址 (免费破解)

CSDN 成就一亿技术人! 今天来讲一下很好用的编辑器 Typora CSDN 成就一亿技术人! 什么是Typora? 它是一个 Markdown 编辑器和阅读器,这意味着您可以使用简单的格式代码 (Markdown)是一种轻量级标记语言&…

muduo网络库剖析——日志Log类

muduo网络库剖析——日志Log类 前情从muduo到my_muduo 概要日志日志级别 框架与细节成员函数 源码 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库,考虑的肯定是众多情况是否可以高效满足;而作为学习者,我们需要抽取其中的精华…

Java的二进制数据处理

在Java中,可以使用二进制运算来处理整数类型数据。 二进制基础知识 二进制(binary)在数学和数字电路中指以2为基数,由0和1组成的数字系统。 位运算符 位运算符是对二进制数进行操作的特殊运算符。在Java中,有以下几…

NCC基础开发技能培训

YonBuilder for NCC 是一个带插件的eclipse工具,跟eclipse没什么区别 NC Cloud2021.11版本开发环境搭建改动 https://nccdev.yonyou.com/article/detail/495 不管是NC Cloud 新手还是老NC开发,在开发NC Cloud时开发环境搭建必看!&#xff…

python基础教程七(布尔类型,条件语句,断言)

1. 布尔类型 在前面,你遇到了很多真值,现在终于需要他们了。真值也称布尔值。 用做布尔表达式(如用作if语句中的条件)时,下面的值都将被解释器视为假: False None 0 "" () [] {} 换而言之&#xff0…

207课程表

题目 你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。 …

Vue2商品规格选择

Vue2Element-ui Vu2仿写拼多多商家后台规则选择&#xff0c;为什么用Vue2呢&#xff0c;因为公司用的Vue2... 样式不是很好看&#xff0c;自己调一下就行。 <template><div ref"inputContainer"><div>{{ combinationsResult }}</div><…

深入浅出Nacos的原理

前言 本文来讲一讲nacos作为底层注册中心的实现原理。那么就有这几个问题&#xff1f; 临时实例和永久实例是什么&#xff1f;有什么区别&#xff1f; 服务实例是如何注册到服务端的&#xff1f; 服务实例和服务端之间是如何保活的&#xff1f; 服务订阅是如何实现的&#…

Adobe illustrator各版本安装指南

下载链接 https://pan.baidu.com/s/11sTpMUbQEXhyjpkBlixcLg?pwd0531 #2024版 1.鼠标右击【Ai2024(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 Ai2024(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击【Setup】选择【以…

【Pytorch】学习记录分享11——GAN对抗生成网络

PyTorch GAN对抗生成网络 0. 工程实现1. GAN对抗生成网络结构2. GAN 构造损失函数&#xff08;LOSS&#xff09;3. GAN对抗生成网络核心逻辑3.1 参数加载&#xff1a;3.2 生成器&#xff1a;3.3 判别器&#xff1a; 0. 工程实现 原理解析&#xff1a; 论文解析&#xff1a;GAN…

canvas如何自定义绘制图片

在Canvas中&#xff0c;可以使用drawImage()方法来绘制图片。该方法接受三个参数&#xff1a; 1. 图片对象&#xff1a;可以是<img>、<canvas>或<video>元素。 2. 图片左上角在Canvas中的X坐标。 3. 图片左上角在Canvas中的Y坐标。 如果要自定义绘制图片&a…

Postman接口测试实战

1.什么是接口测试 来自百度百科的解释&#xff1a; 接口测试是测试系统组件间接口的一种测试&#xff0c;主要用于测试系统与外部其他系统之间的接口&#xff0c;以及系统内部各个子模块之间的接口。测试的重点是要检查接口参数传递的正确性&#xff0c;接口功能实现的正确性&…

使用.Net nanoFramework为ESP32进行蓝牙配网

通过前面的介绍&#xff0c;我们已经学会了如何使用 .NET nanoFramework 为 ESP32 设备连接 Wi-Fi 网络。然而&#xff0c;在实际的物联网环境中&#xff0c;我们往往需要使用更便捷的式来满足配网需求。这篇文章将带你了解一些常见的配网方案&#xff0c;并以 ESP32 为例&…

Java运算符简单介绍

文章目录 1. 算术运算符2. 赋值运算符3. 比较&#xff08;关系&#xff09;运算符4. 逻辑运算符5. 位运算符6. 条件运算符&#xff08;三元运算符&#xff09;7. 运算符优先级 1. 算术运算符 &#xff1a;加法 int a 5; int b 3; int sum a b; // 结果为8-&#xff1a;减…

docker——docker compose简介和案例(部署prometheus+granfana+node-exporter)

docker compose Docker Compose 是 Docker 官⽅编排&#xff08;Orchestration&#xff09;项⽬之⼀&#xff0c;负责快速的部署分布式应⽤。 它允许⽤户通过⼀个单独的 docker-compose.yml 模板⽂件 &#xff08;YAML 格式&#xff09;来定义⼀组相关联的应⽤容器为⼀个项⽬…

基于java,springboot的论旅游管理系统设计与实现

环境以及简介 基于java,springboot的论旅游管理系统设计与实现&#xff0c;Java项目&#xff0c;SpringBoot项目&#xff0c;含开发文档&#xff0c;源码&#xff0c;数据库以及ppt 源码下载 环境配置&#xff1a; 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服…