大云海山数据库(He3DB)源码详解:He3DB-SimpleLruReadPage
背景
大云He3DB 采用了先进的存储引擎和查询优化技术,能够快速处理大量数据和复杂查询。无论是 OLTP(在线事务处理)还是 OLAP(在线分析处理)场景,都能提供出色的性能表现。He3DB 具备完善的数据备份和恢复机制,能够在系统故障或数据损坏时快速恢复数据,确保业务的连续性。He3DB 支持水平扩展和垂直扩展,可以轻松应对不断增长的数据需求。He3DB 提供了严格的访问控制和数据加密功能,确保数据的安全性和隐私性。
本文基于大云He3DB,针对SimpleLruReadPage进行源码解读分享
SimpleLruReadPage
源码解读
c
/*
ctl:指向 SLRU 控制结构的指针,包含共享状态和其他控制信息。
pageno:要读取的页面编号。
write_ok:是否允许对页面进行写操作。
xid:当前事务 ID
*/
int
SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
TransactionId xid)
{
LOG_FUNCTION_ENTRY();
SlruShared shared = ctl->shared;// 初始化共享状态
/* 外层循环:处理 I/O 等待
如果页面正在被其他进程读取或写入,当前进程需要等待
*/
for (;;)
{
int slotno = 0;
bool ok = false;//用于标记页面读取是否成功
/* 尝试找到页面是否已在内存中。如果页面不在内存中,则选择一个可以替换的槽位*/
slotno = SlruSelectLRUPage(ctl, pageno);
/*检查选定槽位的页面编号是否与请求的页面编号匹配,并且页面状态不是空闲 */
if (shared->page_number[slotno] == pageno &&
shared->page_status[slotno] != SLRU_PAGE_EMPTY)
{
/*
检查页面是否正在被读取(SLRU_PAGE_READ_IN_PROGRESS)或正在被写入且不允许写操作
*/
if (shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS ||
(shared->page_status[slotno] == SLRU_PAGE_WRITE_IN_PROGRESS &&
!write_ok))
{
SimpleLruWaitIO(ctl, slotno);//如果页面正在被读取或写入,调用 SimpleLruWaitIO 等待 I/O 完成,然后重新检查页面状态
continue;
}
// 页面已准备好
SlruRecentlyUsed(shared, slotno);//标记页面为最近使用,更新 LRU 状态
pgstat_count_slru_page_hit(shared->slru_stats_idx);//更新统计信息,记录页面命中次数
LOG_FUNCTION_EXIT();
return slotno;
}
/* We found no match; assert we selected a freeable slot */
Assert(shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
(shared->page_status[slotno] == SLRU_PAGE_VALID &&
!shared->page_dirty[slotno]));
/* 将槽位标记为正在读取(SLRU_PAGE_READ_IN_PROGRESS),并清除脏页标志 */
shared->page_number[slotno] = pageno;
shared->page_status[slotno] = SLRU_PAGE_READ_IN_PROGRESS;
shared->page_dirty[slotno] = false;
/* Acquire per-buffer lock (cannot deadlock, see notes at top) */
LWLockAcquire(&shared->buffer_locks[slotno].lock, LW_EXCLUSIVE);
/* Release control lock while doing I/O */
LWLockRelease(shared->ControlLock);
/* 从磁盘读取页面数据到槽位 */
ok = SlruPhysicalReadPage(ctl, pageno, slotno);
/* 将新读取的页面的 LSN(Log Sequence Number)设置为零*/
SimpleLruZeroLSNs(ctl, slotno);
LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE);
//断言页面状态为正在读取,并根据读取结果更新页面状态
Assert(shared->page_number[slotno] == pageno &&
shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS &&
!shared->page_dirty[slotno]);
shared->page_status[slotno] = ok ? SLRU_PAGE_VALID : SLRU_PAGE_EMPTY;
LWLockRelease(&shared->buffer_locks[slotno].lock);
/* 如果页面读取失败,调用 SlruReportIOError 报告错误 */
if (!ok) {
SlruReportIOError(ctl, pageno, xid);
}
else {
HE3_LOG_PRINT("he3db file %s func %s line %d if statement no else",
__FILE__, __FUNCTION__, __LINE__);
}
SlruRecentlyUsed(shared, slotno);//标记页面为最近使用,更新 LRU 状态
/* 更新统计信息,记录页面未命中次数 */
pgstat_count_slru_page_read(shared->slru_stats_idx);
LOG_FUNCTION_EXIT();
return slotno;
}
LOG_FUNCTION_EXIT();
return;
}
函数流程图
该函数流程图如下所示:
流程图解释
-
开始:
- 函数开始执行。
-
调用
SlruSelectLRUPage
获取槽位:- 尝试找到页面是否已在内存中,或选择一个可以替换的槽位。
-
槽位页面是否匹配:
- 检查槽位的页面编号是否与请求的页面编号匹配。
-
页面状态是否为
READ_IN_PROGRESS
或WRITE_IN_PROGRESS
:- 如果页面正在被读取或写入,需要等待 I/O 完成。
-
调用
SimpleLruWaitIO
等待 I/O 完成:- 等待页面的 I/O 操作完成。
-
重新检查页面状态:
- I/O 完成后,重新检查页面状态。
-
检查槽位是否为空或未脏:
- 确保槽位可以被使用。
-
标记槽位为
READ_IN_PROGRESS
:- 标记槽位为正在读取状态。
-
获取槽位锁:
- 获取槽位的独占锁,确保线程安全。
-
释放控制锁:
- 释放控制锁,允许其他进程访问 SLRU 缓冲区。
-
调用
SlruPhysicalReadPage
读取页面:- 从磁盘读取页面数据到槽位。
-
设置 LSN 为零:
- 初始化页面的 LSN。
-
重新获取控制锁:
- 重新获取控制锁,更新页面状态。
-
读取是否成功:
- 检查页面读取是否成功。
-
更新页面状态为
VALID
或EMPTY
:- 根据读取结果更新页面状态。
-
释放槽位锁:
- 释放槽位的独占锁。
-
标记页面为最近使用:
- 更新 LRU 状态。
-
更新统计信息:
- 记录页面命中或未命中的统计信息。
-
返回槽号:
- 返回槽号,函数结束。
函数调用栈
通过source insight
可以查看函数的调用栈
source insight
安装流程可以参考这篇文章:Source insight 工具安装及使用方法
总结
本文基于大云He3DB,针对SimpleLruReadPage进行源码解读分享。
函数名 | 作用 |
---|---|
SubTransSetParent | SimpleLruReadPage 函数的作用是从 SLRU 缓冲区中读取一个页面。它通过以下步骤实现:检查页面是否已在内存中。如果页面正在被读取或写入,等待 I/O 完成。如果页面不在内存中,选择一个空闲槽位。从磁盘读取页面数据到槽位。更新页面状态并返回槽号。 |
其余文章参考链接
大云海山数据库(He3DB)源码详解:He3DB-CLOG日志管理器函数之TransactionIdSetTreeStatus
大云海山数据库(He3DB)+AI(五):一种基于强化学习的数据库旋钮调优方法
大云海山数据库(He3DB)+AI(四):一种基于迁移学习的启发式数据库旋钮调优方法
大云海山数据库(He3DB)源码解读:海山PG 词法、语法分析
大云海山数据库(He3DB)源码详解:海山PG 空闲空间映射表FSM
大云海山数据库(He3DB)源码详解:主备复制SyncRepWaitForLSN
作者信息
公司 | 职位 |
---|---|
中移苏研 | 助理软件研发工程师 |