一、HugePage 是什么

  • Linux 内核提供的内存管理特性,将物理页大小从默认 4 KiB 提升到 2 MiB(x86_64)或 1 GiB(大页 HugePage)。
  • 优点:减少 TLB miss、降低页表内存、提升顺序扫描性能。
  • 接口:内核参数 vm.nr_hugepages = N 控制预留多少大页;进程通过 mmap(MAP_HUGETLB)shmget(SHM_HUGETLB) 申请。

二、vm.nr_hugepages = 0 的含义

  • 0 表示系统不预留任何 HugePage,等同于关闭该特性。
  • 运行时设置立即生效,重启后需写进 /etc/sysctl.d/*.conf 才能持久化。
  • 设置后已分配的大页会被内核逐步回收(无进程使用时)。

三、PostgreSQL 何时会用到 HugePage

  • 代码路径:shmget(SHM_HUGETLB, size) 申请共享内存段(shared_buffers)。
  • 成功条件:
    1. vm.nr_hugepages > 0 且空闲页足够;
    2. 进程 rlimit(RLIMIT_MEMLOCK) ≥ 申请大小;
    3. 挂载点 /dev/hugetlbfs 存在且可写(可选)。
  • 若任一条件不满足,PostgreSQL 会回退到普通 4 KiB 页,不影响功能;但 Patroni 容器场景下常因“半吊子”配置而触发 SIGBUS

四、为什么在统信 UOS + 容器里出现 Bus error (core dumped)

层级 默认情况 结果
节点 vm.nr_hugepages = 512 内核预留 1 GiB 大页
容器 ulimit -l = 64 kiB 无法锁定任何大页
运行时 /dev/shm = 64 MiB 共享内存越界
文件系统 XFS + prjquota mmap 对齐失败

触发链
initdb → mmap(HUGETLB, shared_buffers=128MB) → 内核分配大页 → 容器 memlock 不足 → 页表项建立失败 → CPU 访问非法物理地址 → SIGBUSBus error (core dumped)

五、解决办法

  1. 直接关闭 HugePage(最简单,数据库收益有限)
    echo 0 | sudo tee /proc/sys/vm/nr_hugepages
    # 持久
    echo "vm.nr_hugepages = 0" | sudo tee /etc/sysctl.d/99-uos-hugepage.conf
    sysctl -p /etc/sysctl.d/99-uos-hugepage.conf
    

更多推荐