数据库课程 CMU15-445 2023 Fall Project-1 Buffer Pool Manager

0 实验结果

1 任务总结

本章按照任务书,需要完成

  1. LRU-K替换策略
  2. 磁盘调度器------后台线程接收请求,处理数据的读/写。
  3. 缓冲池管理------使用上面完成的功能,来对抽象的页操作。
1.1 LRU-K替换策略

每个函数的说明都很清楚,按照指示来写即可。

主要说明一些坑点

1.1.1 变量及其作用

时间戳这里要提一下,因为RecordAccess的访问很频繁,时间很短,获取真实的时间戳作用不大。

所以可以每RecordAccess一次,就递增当前的时间戳,计算 K距离时,通过当前时间戳和从当前开始向前数第K次的作差。

cpp 复制代码
// 可以被淘汰置换出的帧数量
size_t curr_size_{0};
// 当前的时间戳
size_t current_timestamp_{0};
1.1.2 坑点

需要明确LRU-K算法,这里算法有点特殊

1.1.2.1 当一个帧访问次数不到K次时,K-距离都是INF,此时比较的是帧最早访问(即第一次)的时间,时间越早,越先被淘汰。

举个例子:当K=3时,此时因为帧1和帧2都没有访问到3次,而帧1最早访问,所以淘汰帧1。

frame_id time_stamp
1 0
2 1
1 2
1.2 磁盘调度器

实现简单,没有坑点,过~

1.3 缓冲池管理

一开始对list,map,page分别上锁,测试无法通过,后改为使用大颗粒锁(即函数从头到尾锁定)。

1.3.1 NewPage

创建新的页面之后,先使用RecordAccess创建节点,再SetEvictable将其设置为Pin。

修改page的元数据,包括:
page_id_pin_count_is_dirty_ 等元数据

1.3.2 FetchPage

获取页面的时候,如果缓冲池中本来就存在,则pin_count_ 需要+1,如果是通过淘汰其他页面得到的,pin_count_ 需要重置为1。

1.3.3 UnpinPage

传入此函数的is_dirty 使用注意:

只有当页面不脏时,需要设置此位为传入的参数。

并且多线程环境下 一定要 每次都执行判断is_dirty并赋值操作。

我在这里遇到的问题,就是它导致的。

[ 2.75] get 2: total_cnt=648 throughput=251.583 avg_throughput=235.808

page seed not consistent: seed_=0 seed=1

2 知识总结

2.1 std::list

一个双向链表容器

尾插入:push_back

头插入: push_front

删除元素:

pop_back

pop_front

erase

获取元素:

front()

back()

2.2 std::optional

表示一个可能存在也可能不存在的值,作用是:使用std::nullopt,避免使用 nullptr 或特殊值(如 -10)来表示"无值"的情况。

方法:

emplace

2.3 std::promise

并发编程中传递值或异常.

可以与 std::future 一起使用,以实现异步操作.
std::promise 可以存储任何类型的值.
std::future::get() 是一个阻塞调用,它会一直等待,直到 std::promise 设置了值或异常.

2.4 std::unordered_map

std::map 是一个有序的关联容器,基于红黑树(一种自平衡二叉搜索树)实现,

平均时间复杂度为 O(log n)。

由于红黑树的结构,内存占用相对较高。

std::unordered_map 是一个无序的关联容器,基于哈希表实现。

平均时间复杂度为 O(1),最坏情况下为 O(n),内存占用相对较低。

std::unordered_map的赋值

c++ 复制代码
std::unordered_map<int,complex_type>data_src;

1. 赋值运算符拷贝
std::unordered_map<int,complex_type>data_src_copy = data_src;
2. 拷贝构造函数
std::unordered_map<int,complex_type>data_src_copy(data_src);

键和值 都会被拷贝到新的 std::unordered_map 容器中,如果是指针类型,仅复制指针地址。

c++ 复制代码
	complex_type& operator=(const complex_type& that)
	{
		std::cout << "赋值重载" << std::endl;
		this->age = that.age;
		this->name = that.name;
		return *this;
	}
    // 结果
    ============
	有参构造函数
	拷贝构造函数
	============
	有参构造函数
	默认构造函数
	赋值重载
	============
	拷贝构造函数
	拷贝构造函数
	============
	赋值重载
	赋值重载
	============
	有参构造函数
	赋值重载
	============
	syh dd

	// 代码
    std::unordered_map<int,complex_type>data_src;
    std::cout << "============" << std::endl;
    data_src.emplace(1,complex_type(10, "syh"));
    std::cout << "============" << std::endl;
    data_src[2] = complex_type(20,"mike");
    std::cout << "============" << std::endl;
    std::unordered_map<int,complex_type>data_src_copy(data_src);// 因为有两个值,所以发生了两次拷贝
    std::cout << "============" << std::endl;
    data_src_copy = data_src;
    std::cout << "============" << std::endl;
    data_src_copy[1] = complex_type(57,"dd");
    std::cout << "============" << std::endl;
    std::cout << data_src[1].name<<" " << data_src_copy[1].name << std::endl;
相关推荐
嵌入(师)几秒前
嵌入式驱动开发详解21(网络驱动开发)
网络·驱动开发
林的快手11 分钟前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
柒烨带你飞37 分钟前
路由器的原理
网络·智能路由器·php
xserver239 分钟前
ensp 基于EASY IP的公司出口链路配置
网络·tcp/ip·智能路由器
枫零NET41 分钟前
学习思考:一日三问(学习篇)之匹配VLAN
网络·学习·交换机
HEU_firejef44 分钟前
Redis——缓存预热+缓存雪崩+缓存击穿+缓存穿透
数据库·redis·缓存
手心里的白日梦1 小时前
UDP传输层通信协议详解
网络·网络协议·udp
KELLENSHAW2 小时前
MySQL45讲 第三十七讲 什么时候会使用内部临时表?——阅读总结
数据库·mysql
红米饭配南瓜汤2 小时前
WebRTC服务质量(11)- Pacer机制(03) IntervalBudget
网络·网络协议·音视频·webrtc·媒体