# 大云海山数据库(He3DB)源码详解:He3DB-SimpleLruReadPage
背景
大云He3DB 接纳了先进的存储引擎和查询优化技术,可以大概快速处理处罚大量数据和复杂查询。无论是 OLTP(在线变乱处理处罚)还是 OLAP(在线分析处理处罚)场景,都能提供精彩的性能表现。He3DB 具备美满的数据备份和规复机制,可以大概在系统故障或数据破坏时快速规复数据,确保业务的连续性。He3DB 支持水平扩展和垂直扩展,可以轻松应对不断增长的数据需求。He3DB 提供了严格的访问控制和数据加密功能,确保数据的安全性和隐私性。
本文基于大云He3DB,针对SimpleLruReadPage举行源码解读分享
SimpleLruReadPage
源码解读
- /*
- 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);
- }
- 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 完成:
- 重新查抄页面状态:
- 查抄槽位是否为空或未脏:
- 标记槽位为 READ_IN_PROGRESS:
- 获取槽位锁:
- 释放控制锁:
- 调用 SlruPhysicalReadPage 读取页面:
- 设置 LSN 为零:
- 重新获取控制锁:
- 读取是否成功:
- 更新页面状态为 VALID 或 EMPTY:
- 释放槽位锁:
- 标记页面为最近使用:
- 更新统计信息:
- 返回槽号:
函数调用栈
通过source insight可以检察函数的调用栈
source insight安装流程可以参考这篇文章:Source insight 工具安装及使用方法
总结
本文基于大云He3DB,针对SimpleLruReadPage举行源码解读分享。
函数名作用SubTransSetParentSimpleLruReadPage 函数的作用是从 SLRU 缓冲区中读取一个页面。它通过以下步骤实现:查抄页面是否已在内存中。如果页面正在被读取或写入,等候 I/O 完成。如果页面不在内存中,选择一个空闲槽位。从磁盘读取页面数据到槽位。更新页面状态并返回槽号。 其余文章参考链接
大云海山数据库(He3DB)源码详解:He3DB-CLOG日志管理器函数之TransactionIdSetTreeStatus
大云海山数据库(He3DB)+AI(五):一种基于强化学习的数据库旋钮调优方法
大云海山数据库(He3DB)+AI(四):一种基于迁移学习的开导式数据库旋钮调优方法
大云海山数据库(He3DB)源码解读:海山PG 词法、语法分析
大云海山数据库(He3DB)源码详解:海山PG 空闲空间映射表FSM
大云海山数据库(He3DB)源码详解:主备复制SyncRepWaitForLSN
作者信息
公司职位中移苏研助理软件研发工程师
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |