查看原文
其他

PostgreSQL 中的 smgr 接口

David Zhang IvorySQL开源数据库社区
2024-09-30
📕概述

在我之前的博客文章中,我解释了惊人的缓冲区标签如何在PostgreSQL中工作,以及如何使用Lustre网络文件系统设置共享存储。在这篇博客中,我将解释 「PostgreSQL 提供的存储接口,以及体验存储接口的想法」,即 smgr,存储管理器。


🐘smgr


smgrPostgreSQL 提供的存储管理器,具有以下公共接口例程来存储表和索引的元组。在我看来,PostgreSQL 主要有三种类型的文件保存在磁盘上:

1)“配置”相关文件,如 postgresql.conf、pg_hba.conf 和 pg_control 等;

2) 预写日志文件,即 WAL;

3)存储表和索引元组的实际文件。旨在仅处理后者。


🐞换句话说,如果要将计算和存储分开,则应以不同的方式考虑这三个类别。这不仅是因为PostgreSQL有不同的逻辑来处理它们,还因为不是为了处理配置和WAL而设计的。以下是 smgr.c:smgrsmgr 中定义的接口 smgr smgr
static const f_smgr smgrsw[] = {
    /* magnetic disk */
    {
        .smgr_init = mdinit,
        .smgr_shutdown = NULL,
        .smgr_open = mdopen,
        .smgr_close = mdclose,
        .smgr_create = mdcreate,
        .smgr_exists = mdexists,
        .smgr_unlink = mdunlink,
        .smgr_extend = mdextend,
        .smgr_prefetch = mdprefetch,
        .smgr_read = mdread,
        .smgr_write = mdwrite,
        .smgr_writeback = mdwriteback,
        .smgr_nblocks = mdnblocks,
        .smgr_truncate = mdtruncate,
        .smgr_immedsync = mdimmedsync,
    }
};
该界面包含存储管理所需的所有必要功能,例如我们都非常熟悉的基本文件操作,包括创建、打开、读取、写入和关闭。实际的实现总是从md开始,因为PostgreSQL在过去被设计用于处理磁盘。 

🚩PostgreSQL可以使用这些接口处理所有表和索引元组,这要归功于魔术缓冲区标签,该标签用于在任何给定时间寻址特定的页面块(8KB)。有关如何使用缓冲区标签的详细信息,可以参考 3.如何使用缓冲区标记

🔗如何使用缓冲区标记
https://www.highgo.ca/2021/07/23/the-amazing-buffer-tag-in-postgresql/



🔨分离计算和存储

要体验smgr界面,一个简单的想法是构建TCP / IP服务器和客户端。看在服务器端」,添加逻辑来实现一些基本接口,如创建、打开、读取、写入和关闭。然后,定义一个简单的协议,以指示具有相应错误代码的不同操作。「在客户端」,将 smgr.c 中的“mdxxxx”替换为可以通过 TCP/IP 连接将这些文件操作转发到服务器端的函数。然后,从服务器读取或写入页面或向服务器写入页面的结果将发送回调用方。


🎄通过这些最小的更改,可以设置一个非常简单的原型来分离计算和存储。但是,如果要将计算和存储分开的工作解决方案,则需要考虑更多因素。一个名为neon的开源计算和存储解决方案旨在通过更全面的设计来实现这一目标。


🐥例如,可以在 pagestore_smgr.c 中找到接口的实现之一,下面显示了一些更改。smgr


static const struct f_smgr neon_smgr =
{
    .smgr_init = neon_init,
    .smgr_shutdown = NULL,
    .smgr_open = neon_open,
    .smgr_close = neon_close,
    .smgr_create = neon_create,
    .smgr_exists = neon_exists,
    .smgr_unlink = neon_unlink,
    .smgr_extend = neon_extend,
    .smgr_prefetch = neon_prefetch,
    .smgr_read = neon_read,
    .smgr_write = neon_write,
    .smgr_writeback = neon_writeback,
    .smgr_nblocks = neon_nblocks,
    .smgr_truncate = neon_truncate,
    .smgr_immedsync = neon_immedsync,

    .smgr_start_unlogged_build = neon_start_unlogged_build,
    .smgr_finish_unlogged_build_phase_1 = neon_finish_unlogged_build_phase_1,
    .smgr_end_unlogged_build = neon_end_unlogged_build,
};

在重新实现或包装这些 SMGR 接口后,可以将表和索引元组写入本地缓存,并生成相应的 WAL 以供以后重做使用。有关更多详细信息,您可以在“pagestore_smgr.c”中查看源代码。



🐣总结

在这篇博文中,我们讨论了smgr接口,并为那些对PostgreSQL如何处理元组存储」感兴趣的人提出了一个简单的想法。我们还为那些想要深入了解PostgreSQL存储细节的人提供了一个真实的例子。




官方网址:
https://www.ivorysql.org/zh-cn/
社区仓库:
https://github.com/IvorySQL/IvorySQL

IvorySQL社区欢迎并赞赏所有类型的贡献,期待您的加入!
还有,别忘了在GitHub给我们一个 ⭐奥~


🐘点击蓝字 阅读原文

继续滑动看下一个
IvorySQL开源数据库社区
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存