大云海山数据库(He3DB)源码详解:He3DB-SimpleLruReadPage

打印 上一主题 下一主题

主题 1016|帖子 1016|积分 3048

# 大云海山数据库(He3DB)源码详解:He3DB-SimpleLruReadPage
背景

大云He3DB 接纳了先进的存储引擎和查询优化技术,可以大概快速处理处罚大量数据和复杂查询。无论是 OLTP(在线变乱处理处罚)还是 OLAP(在线分析处理处罚)场景,都能提供精彩的性能表现。He3DB 具备美满的数据备份和规复机制,可以大概在系统故障或数据破坏时快速规复数据,确保业务的连续性。He3DB 支持水平扩展和垂直扩展,可以轻松应对不断增长的数据需求。He3DB 提供了严格的访问控制和数据加密功能,确保数据的安全性和隐私性。
本文基于大云He3DB,针对SimpleLruReadPage举行源码解读分享
SimpleLruReadPage

源码解读

  1. /*
  2. ctl:指向 SLRU 控制结构的指针,包含共享状态和其他控制信息。
  3. pageno:要读取的页面编号。
  4. write_ok:是否允许对页面进行写操作。
  5. xid:当前事务 ID
  6. */
  7. int
  8. SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
  9.                                   TransactionId xid)
  10. {
  11.         LOG_FUNCTION_ENTRY();
  12.         SlruShared        shared = ctl->shared;// 初始化共享状态
  13.         /*  外层循环:处理 I/O 等待
  14.     如果页面正在被其他进程读取或写入,当前进程需要等待
  15.      */
  16.         for (;;)
  17.         {
  18.                 int slotno = 0;
  19.                 bool ok = false;//用于标记页面读取是否成功
  20.                 /* 尝试找到页面是否已在内存中。如果页面不在内存中,则选择一个可以替换的槽位*/
  21.                 slotno = SlruSelectLRUPage(ctl, pageno);
  22.                 /*检查选定槽位的页面编号是否与请求的页面编号匹配,并且页面状态不是空闲 */
  23.                 if (shared->page_number[slotno] == pageno &&
  24.                         shared->page_status[slotno] != SLRU_PAGE_EMPTY)
  25.                 {
  26.                         /*
  27.                          检查页面是否正在被读取(SLRU_PAGE_READ_IN_PROGRESS)或正在被写入且不允许写操作
  28.                          */
  29.                         if (shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS ||
  30.                                 (shared->page_status[slotno] == SLRU_PAGE_WRITE_IN_PROGRESS &&
  31.                                  !write_ok))
  32.                         {
  33.                                 SimpleLruWaitIO(ctl, slotno);//如果页面正在被读取或写入,调用 SimpleLruWaitIO 等待 I/O 完成,然后重新检查页面状态
  34.                                
  35.                                 continue;
  36.                         }
  37.             //  页面已准备好
  38.                         SlruRecentlyUsed(shared, slotno);//标记页面为最近使用,更新 LRU 状态
  39.                         pgstat_count_slru_page_hit(shared->slru_stats_idx);//更新统计信息,记录页面命中次数
  40.                         LOG_FUNCTION_EXIT();
  41.                         return slotno;
  42.                 }
  43.                 /* We found no match; assert we selected a freeable slot */
  44.                 Assert(shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
  45.                            (shared->page_status[slotno] == SLRU_PAGE_VALID &&
  46.                                 !shared->page_dirty[slotno]));
  47.                 /* 将槽位标记为正在读取(SLRU_PAGE_READ_IN_PROGRESS),并清除脏页标志 */
  48.                 shared->page_number[slotno] = pageno;
  49.                 shared->page_status[slotno] = SLRU_PAGE_READ_IN_PROGRESS;
  50.                 shared->page_dirty[slotno] = false;
  51.                 /* Acquire per-buffer lock (cannot deadlock, see notes at top) */
  52.                 LWLockAcquire(&shared->buffer_locks[slotno].lock, LW_EXCLUSIVE);
  53.                 /* Release control lock while doing I/O */
  54.                 LWLockRelease(shared->ControlLock);
  55.                 /* 从磁盘读取页面数据到槽位 */
  56.                 ok = SlruPhysicalReadPage(ctl, pageno, slotno);
  57.                 /* 将新读取的页面的 LSN(Log Sequence Number)设置为零*/
  58.                 SimpleLruZeroLSNs(ctl, slotno);
  59.        
  60.                 LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE);
  61. //断言页面状态为正在读取,并根据读取结果更新页面状态
  62.                 Assert(shared->page_number[slotno] == pageno &&
  63.                            shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS &&
  64.                            !shared->page_dirty[slotno]);
  65.                 shared->page_status[slotno] = ok ? SLRU_PAGE_VALID : SLRU_PAGE_EMPTY;
  66.                 LWLockRelease(&shared->buffer_locks[slotno].lock);
  67.                 /* 如果页面读取失败,调用 SlruReportIOError 报告错误 */
  68.                 if (!ok) {
  69.                         SlruReportIOError(ctl, pageno, xid);
  70.                 }
  71.                 SlruRecentlyUsed(shared, slotno);//标记页面为最近使用,更新 LRU 状态
  72.                 /* 更新统计信息,记录页面未命中次数 */
  73.                 pgstat_count_slru_page_read(shared->slru_stats_idx);
  74.                 LOG_FUNCTION_EXIT();
  75.                 return slotno;
  76.         }
  77.         LOG_FUNCTION_EXIT();
  78.         return;
  79. }
复制代码
函数流程图

该函数流程图如下所示:

流程图表明


  • 开始

    • 函数开始实行。

  • 调用 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举行源码解读分享。
函数名作用SubTransSetParentSimpleLruReadPage 函数的作用是从 SLRU 缓冲区中读取一个页面。它通过以下步骤实现:查抄页面是否已在内存中。如果页面正在被读取或写入,等候 I/O 完成。如果页面不在内存中,选择一个空闲槽位。从磁盘读取页面数据到槽位。更新页面状态并返回槽号。 其余文章参考链接

大云海山数据库(He3DB)源码详解:He3DB-CLOG日志管理器函数之TransactionIdSetTreeStatus
大云海山数据库(He3DB)+AI(五):一种基于强化学习的数据库旋钮调优方法
大云海山数据库(He3DB)+AI(四):一种基于迁移学习的开导式数据库旋钮调优方法
大云海山数据库(He3DB)源码解读:海山PG 词法、语法分析
大云海山数据库(He3DB)源码详解:海山PG 空闲空间映射表FSM
大云海山数据库(He3DB)源码详解:主备复制SyncRepWaitForLSN
作者信息

公司职位中移苏研助理软件研发工程师
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

尚未崩坏

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表