PostgreSQL码农集散地

PostgreSQL 19 preview - 监控跨CPU访问内存问题

本期播客

PostgreSQL 19 preview - 监控跨CPU访问内存问题

在 NUMA 架构中,不同的 CPU 拥有访问速度更快的本地内存。如果一个进程访问了非本地的内存(即位于另一个 NUMA 节点的内存),性能可能会受到影响。通过监控共享缓冲区的 NUMA 分布,可以帮助识别潜在的内存访问不均衡或性能问题。

由于 PostgreSQL 数据库块(默认 8KB)可能大于 OS 内存页(通常是 4KB),一个缓冲区可能跨越多个 OS 内存页,因此一个 bufferid 可能对应多行记录,每行有不同的 os_page_num 和 numa_node。

pg_buffercache 18 引入了监控含NUMA信息的buffer监控信息, 补丁如下. 但是有个小问题, 19已修复, 看后面的补丁.

https://github.com/postgres/postgres/commit/ba2a3c2302f1248496322eba917b17a421499388

Add pg_buffercache_numa view with NUMA node info  
Introduces a new view pg_buffercache_numa, showing NUMA memory nodes  
for individual buffers. For each buffer the view returns an entry for
each memory page, with the associated NUMA node.  

The database blocks and OS memory pages may have different size - the  
default block size is 8KB, while the memory page is 4K (on x86). But  
other combinations are possible, depending on configure parameters,  
platform, etc. This means buffers may overlap with multiple memory  
pages, each associated with a different NUMA node.  

To determine the NUMA node for a buffer, we first need to touch the  
memory pages using pg_numa_touch_mem_if_required, otherwise we might get  
status -2 (ENOENT = The page is not present), indicating the page is  
either unmapped or unallocated.  

The view may be relatively expensive, especially when accessed for the  
first time in a backend, as it touches all memory pages to get reliable  
information about the NUMA node. This may also force allocation of the  
shared memory.  

Author: Jakub Wartak <[email protected]>  
Reviewed-by: Andres Freund <[email protected]>  
Reviewed-by: Bertrand Drouvot <[email protected]>  
Reviewed-by: Tomas Vondra <[email protected]>  
Discussion: https://postgr.es/m/CAKZiRmxh6KWo0aqRqvmcoaX2jUxZYb4kGp3N%3Dq1w%2BDiH-696Xw%40mail.gmail.com  

这个 Git 补丁(Commit ba2a3c2302f1248496322eba917b17a421499388)是对 PostgreSQL 的 pg_buffercache 扩展模块的一次重要增强,主要目的是引入对 NUMA(非统一内存访问)架构的感知和监控能力。

请注意,你上一个解读的补丁(4b203d499c610160e9867e6add2366780429344c)正是基于这个补丁的功能进行了优化和泛化。这个补丁是实现 NUMA 监控的第一步。

补丁摘要

  • 提交信息(Commit Message):Add pg_buffercache_numa view with NUMA node info
  • 作者: Jakub Wartak
  • 模块版本提升: 从 1.5 升级到 1.6。

核心目的和解决的问题

该补丁旨在允许数据库管理员和性能调优人员检查 PostgreSQL 共享缓冲区(Shared Buffers)中的页面是如何分布在不同的 NUMA 内存节点上。

在 NUMA 架构中,不同的 CPU 拥有访问速度更快的本地内存。如果一个进程访问了非本地的内存(即位于另一个 NUMA 节点的内存),性能可能会受到影响。通过监控共享缓冲区的 NUMA 分布,可以帮助识别潜在的内存访问不均衡或性能问题。

补丁引入的主要更改

该补丁新增了一个函数和一个视图,以提供缓冲区与其 NUMA 节点之间的映射关系。

  1. 新增 SQL 函数 pg_buffercache_numa_pages()

  • 由于数据库块(默认 8KB)可能大于 OS 内存页(通常是 4KB),一个缓冲区可能跨越多个 OS 内存页,因此一个 bufferid 可能对应多行记录,每行有不同的 os_page_num 和 numa_node。
  • 为了获取可靠的 NUMA 节点信息,该函数必须主动“触摸”或访问内存页(通过 pg_numa_touch_mem_if_required 等机制),否则可能会得到页面未分配或不可用的状态(-2)。
  • 注意: 正如提交信息所指出的,首次访问这个函数或视图可能会相对昂贵,因为它会强制访问所有共享内存页以获取准确的 NUMA 信息,这可能还会触发共享内存的实际分配。
  • bufferid (integer):共享缓冲区 ID。
  • os_page_num (int4):对应的操作系统内存页码。
  • numa_node (int4):该 OS 内存页所在的 NUMA 节点 ID。
  • 这是一个 C 语言实现的集合返回函数 (Set-Returning Function, SRF)。
  • 它返回一个结果集,包含三个字段:
  • 关键实现细节:
  • 权限: 该函数被授予 pg_monitor 角色执行权限,但禁止 PUBLIC 访问。
  • 新增 SQL 视图 pg_buffercache_numa

    • 这是一个基于 pg_buffercache_numa_pages() 函数的便利视图。
    • 它将函数的输出字段命名为 bufferid, os_page_num, numa_node,便于用户直接查询。
    • 权限: 该视图被授予 pg_monitor 角色查询权限,但禁止 PUBLIC 访问。

    总结

    这个补丁是 pg_buffercache 扩展中引入 NUMA 监控功能的基础,它让用户可以查看共享缓冲区中的数据块是如何分布在底层 NUMA 硬件架构上的,这对于高级性能分析和 NUMA 调优至关重要。

    (如你所见,在你上一个查询中,4b203d499c610160e9867e6add2366780429344c 补丁正是解决了这个补丁引入的功能在缺乏 libnuma 支持时会失败的问题。)


    pg_buffercache 18 引入了监控含NUMA信息的buffer监控信息, 但是有个小问题, 19已修复, 补丁如下.

    https://github.com/postgres/postgres/commit/4b203d499c610160e9867e6add2366780429344c

    pg_buffercache: Add pg_buffercache_os_pages  
    ba2a3c2 has added a way to check if a buffer is spread across  
    multiple pages with some NUMA information, via a new view  
    pg_buffercache_numa that depends on pg_buffercache_numa_pages(), a SQL  
    function.  These can only be queried when support for libnuma exists,  
    generating an error if not.  

    However, it can be useful to know how shared buffers and OS pages map  
    when NUMA is not supported or not available.  This commit expands the  
    capabilities around pg_buffercache_numa:  
    - pg_buffercache_numa_pages() is refactored as an internal function,  
    able to optionally process NUMA.  Its SQL definition prior to this  
    commit is still around to ensure backward-compatibility with v1.6.  
    - A SQL function called pg_buffercache_os_pages() is added, able to work  
    with or without NUMA.  
    - The view pg_buffercache_numa is redefined to use  
    pg_buffercache_os_pages().  
    - A new view is added, called pg_buffercache_os_pages.  This ignores  
    NUMA for its result processing, for a better efficiency.  

    The implementation is done so as there is no code duplication between  
    the NUMA and non-NUMA views/functions, relying on one internal function
    that does the job for all of them.  The module is bumped to v1.7.  

    Author: Bertrand Drouvot <[email protected]>  
    Reviewed-by: Mircea Cadariu <[email protected]>  
    Reviewed-by: Michael Paquier <[email protected]>  
    Discussion: https://postgr.es/m/Z/[email protected]  

    这个 Git 补丁(Commit 4b203d499c610160e9867e6add2366780429344c)是对 PostgreSQL 的 pg_buffercache 扩展模块的一次功能性增强。

    补丁摘要

    • 提交信息(Commit Message):pg_buffercache: Add pg_buffercache_os_pages
    • 作者: Bertrand Drouvot
    • 模块版本提升: 从 1.6 升级到 1.7。

    核心目的和解决的问题

    在引入此补丁之前,pg_buffercache 扩展提供了获取共享缓冲区(shared buffers)和操作系统(OS)内存页(OS pages)之间映射关系的功能,同时还可以提供 NUMA(非统一内存访问)节点信息。然而,这个功能(通过 pg_buffercache_numa_pages() 函数和 pg_buffercache_numa 视图实现)依赖于系统对 libnuma 的支持。如果系统不支持 NUMA,查询这些功能会报错。

    这个补丁的目的是:允许用户在不依赖 NUMA 支持的情况下,也能查看共享缓冲区与其对应的 OS 内存页的映射关系。

    补丁引入的主要更改

    该补丁通过重构代码和引入新的 SQL 对象来实现其目标:

    1. 新增 SQL 函数 pg_buffercache_os_pages(boolean)

    • 这是一个新的通用 C 函数的 SQL 封装。
    • 它接受一个布尔参数 include_numa。
    • 如果参数为 true,则返回包含 NUMA 节点信息的完整结果(与原来的 pg_buffercache_numa 类似)。
    • 如果参数为 false,则只返回缓冲区 ID 和 OS 页码,忽略 NUMA 信息,这可以在不支持 NUMA 的系统上正常工作,并且效率更高。
  • 新增 SQL 视图 pg_buffercache_os_pages

    • 这个视图是基于新函数 pg_buffercache_os_pages(false) 创建的。
    • 它提供了一个简洁、高效的方式来查看共享缓冲区到 OS 页的映射,不包含 NUMA 节点信息。
  • 重定义现有视图 pg_buffercache_numa

    • 原有的 pg_buffercache_numa 视图被重新定义,现在它基于新函数 pg_buffercache_os_pages(true)。
    • 这确保了向后兼容性,并集中了 NUMA 相关的逻辑。
  • 代码结构优化

    • 作者将所有逻辑集中在一个内部 C 函数中,避免了 NUMA 和非 NUMA 场景下的代码重复。

    总而言之,这个补丁将缓冲区到 OS 页面映射的监控能力推广到了所有系统配置,不再强制要求 NUMA 支持,同时通过引入新的视图提供了一个更轻量级的查询选项。