国产化适配:大厂 PG 内核信创环境移植 —— 完整方案

  先用大白话把这件事讲清楚,再给你能直接用的完整代码和流程。

  ---
  一、先搞懂到底在干什么(大白话)

  "大厂 PG 内核" 指的是基于 PostgreSQL 改的数据库(人大金仓 KingbaseES、瀚高 HighGo、华为 openGauss、阿里 PolarDB、腾讯
  TDSQL-PG 等都是 PG 血统)。

 "信创环境" 就是把它从 Intel + CentOSs这种"洋环境",搬到国产芯片 + 国产操作系统上跑起来,而且要跑得稳、跑得快。

  国产环境无非这几类,移植难度差别很大:

  ┌─────────────┬───────────────┬─────────────────┬─────────────────┬─────────────────────────────────────────────┐
  │    类别     │     代表      │   指令集架构    │    移植难度     │                    说明                     │
  ├─────────────┼───────────────┼─────────────────┼─────────────────┼─────────────────────────────────────────────┤
  │ 鲲鹏 / 飞腾 │ 华为/飞腾     │ ARM64 (aarch64) │ ⭐⭐ 低         │ PG 原生支持好,主要是编译参数和调优         │
  ├─────────────┼───────────────┼─────────────────┼─────────────────┼─────────────────────────────────────────────┤
  │ 海光 / 兆芯 │ Hygon/Zhaoxin │ x86_64          │ ⭐ 最低         │ 几乎等同于 Intel,重点是 RPM 依赖           │
  ├─────────────┼───────────────┼─────────────────┼─────────────────┼─────────────────────────────────────────────┤
  │ 龙芯        │ Loongson      │ LoongArch64     │ ⭐⭐⭐⭐ 高     │ 新架构,老版本 PG 要手动移植自旋锁/原子操作 │
  ├─────────────┼───────────────┼─────────────────┼─────────────────┼─────────────────────────────────────────────┤
  │ 申威        │ Sunway        │ SW64            │ ⭐⭐⭐⭐⭐ 最高 │ 编译器和工具链都特殊,最难                  │
  └─────────────┴───────────────┴─────────────────┴─────────────────┴─────────────────────────────────────────────┘

  操作系统:麒麟 Kylin V10、统信 UOS、openEuler、中标麒麟(基本都是 RHEL/Debian 系,glibc 版本和依赖包名不一样)。

  一句话总结移植的本质:

  ▎ 90% 的工作量是「让编译器认识新 CPU + 凑齐依赖库 + 跑通回归测试」,只有 10% 是真正改 C 源码里跟 CPU
  ▎ 强相关的那几个文件(自旋锁、原子操作、内存屏障、CRC 硬件加速)。

  下面分别给你这两部分的完整代码。

  ---
  二、完整流程总览(七步法)

  ①摸底     →确认 CPU架构 + OS + glibc + 编译器版本
  ②工具链   →装齐 gcc/依赖库,搭隔离的编译环境
  ③配置     →configure 识别架构 + 正确的 march 参数
  ④源码移植 →改自旋锁/原子操作/内存屏障/CRC(仅龙芯/申威需要)
  ⑤编译     →全量编译 + 解决报错
  ⑥验证     →make check 回归测试 + 性能压测
  ⑦打包     →做成 RPM/DEB,适配国产 OS

  ---
  三、第①步:摸底(先跑这个脚本)

  大白话:移植前必须先知道"敌人"长啥样。下面这个脚本一把梭,把环境信息全打出来。

  #!/bin/bash
  # detect_env.sh ——信创环境摸底脚本(直接复制运行)
  echo "========= CPU 架构 ========="
  uname -m                              # aarch64 / loongarch64 / x86_64 / sw_64
  echo "========= CPU 型号 ========="
  lscpu | grep -iE "model name|架构|Architecture|BIOS"
  cat /proc/cpuinfo | grep -iE "model|cpu" | head -5

  echo "========= 操作系统 ========="
  cat /etc/os-release | grep -iE "PRETTY_NAME|VERSION"
  # 麒麟看这个:
  [ -f /etc/kylin-release ] && cat /etc/kylin-release

  echo "========= glibc 版本(关键!决定二进制能不能跑)========="
  ldd --version | head -1
  getconf GNU_LIBC_VERSION

  echo "========= 编译器 ========="
  gcc --version | head -1
  gcc -dumpmachine                      # 确认目标三元组

  echo "========= ARM 是否支持 CRC 硬件加速 ========="
  grep -o 'crc32\|asimd\|crc' /proc/cpuinfo | sort -u

  echo "========= 关键开发库 ========="
  for lib in readline-devel zlib-devel openssl-devel libicu-devel \
             flex bison perl-devel python3-devel libxml2-devel; do
      rpm -q $lib 2>/dev/null || echo "缺少: $lib"
  done

  重点看三个东西:
  - uname -m →决定走哪条移植路线
  - glibc 版本 →这是最隐蔽的坑。麒麟 V10 是 glibc 2.28,如果你拿 glibc 2.34 的环境编译,到目标机器上会报 version
  GLIBC_2.34 not found,必须在目标 OS 同款环境里编译。
  - ARM 的 crc32 标志 →决定能不能开硬件 CRC 加速(PG 性能关键)。

  ---
  四、第②步:工具链+ 依赖(一键装齐)

  大白话:别在物理机上瞎装,用 Docker 拉国产 OS 镜像做隔离编译环境,干净、可复现。

  # ===== 麒麟/openEuler ARM64 编译环境(RPM 系)=====
  # openEuler 官方有 ARM64/LoongArch 镜像,最省事
  docker run -it --name pg-build openeuler/openeuler:22.03-lts-sp1 bash

  # 进容器后装齐 PG 编译依赖(一行搞定)
  yum install -y gcc gcc-c++ make flex bison \
      readline-devel zlib-devel openssl-devel \
      libicu-devel libxml2-devel libxslt-devel \
      perl-devel python3-devel tcl-devel \
      systemd-devel uuid-devel lz4-devel \
      perl-IPC-Run perl-Test-Simple   # 回归测试要用

  # ===== 统信UOS / Deepin(DEB 系)=====
  apt-get update && apt-get install -y \
      gcc make flex bison \
      libreadline-dev zlib1g-dev libssl-dev \
      libicu-dev libxml2-dev libxslt1-dev \
      perl libperl-dev python3-dev tcl-dev \
      libsystemd-dev uuid-dev liblz4-dev

  ▎ 避坑:libicu-devel(排序规则库)经常被忽略,缺了它中文排序会乱。openssl-devel 国产 OS 里可能是国密版
  ▎ tongsuo/tassl,要支持国密 SM2/SM3/SM4 时换成它。

  ---
  五、第③步:configure配置(架构识别 + 编译参数)

  大白话:configure 是 PG 的"配置向导",它要先认识你的 CPU 才能编译。ARM64 和 x86 PG
  都认识,龙芯老版本不认识,得手动告诉它。

  5.1 ARM64(鲲鹏/飞腾)——最优编译参数

  # ===== 鲲鹏 920 / 飞腾 D2000 最佳编译配置 =====
  export CFLAGS="-O2 -march=armv8-a+crc+crypto -mtune=tsv110 -fno-omit-frame-pointer"
  # 飞腾用 -mtune=generic 或不写;鲲鹏920用 tsv110
  # +crc 是关键:开启 CRC32C 硬件指令,PG 校验和性能翻几倍

  ./configure \
      --prefix=/opt/pg/16 \
      --with-icu \
      --with-openssl \
      --with-llvm=no \
      --with-readline \
      --with-libxml \
      --with-lz4 \
      --with-uuid=e2fs \
      --with-systemd \
      --enable-thread-safety \
      CFLAGS="$CFLAGS"

  # ===== 海光/兆芯 (x86_64) ——几乎等同 Intel =====
  export CFLAGS="-O2 -march=x86-64-v2 -mtune=generic"
  # 兆芯老型号可能不支持 v2,保守用 -march=core2 或 nehalem
  ./configure --prefix=/opt/pg/16 --with-icu --with-openssl ...(同上)

  5.2 龙芯 LoongArch64 ——老版本 PG 要打补丁

  PostgreSQL 16+ 已原生支持 LoongArch,直接 configure 即可:

  export CFLAGS="-O2 -march=loongarch64 -mabi=lp64d"
  ./configure --prefix=/opt/pg/16 --build=loongarch64-linux-gnu ...

  PG 15 及更老版本,configure 不认识龙芯,要手动改 config.guess /
  config.sub(用龙芯官方提供的新版替换),并改一个宏,下一节给代码。

  ---
  六、第④步:源码移植关键代码(仅龙芯/申威需要,ARM/x86跳过)

  这是真正的硬核移植部分。大白话:CPU
  越底层的并发原语(自旋锁、原子操作、内存屏障)越跟指令集绑死,新架构必须手写汇编。下面给龙芯 LoongArch
  的完整移植代码(最常见的硬骨头)。

  6.1 自旋锁 ——src/include/storage/s_lock.h

  大白话:自旋锁是数据库并发的命根子,就是"抢锁抢不到就原地转圈等"。要用龙芯的原子交换指令 amswap.w 实现。

  在 s_lock.h 里找到一堆 #if defined(__arm__)... 的地方,新增龙芯分支:

  /* ===== LoongArch (龙芯) 自旋锁实现 ===== */
  #if defined(__loongarch__) || defined(__loongarch64)
  #define HAS_TEST_AND_SET

  typedef unsigned int slock_t;

  #define TAS(lock)  tas(lock)

  static __inline__ int
  tas(volatile slock_t *lock)
  {
      int ret;
      /* amswap.w:原子地把 1 写进锁,返回锁的旧值。
         旧值==0 说明我抢到了;旧值==1 说明别人占着。 */
      __asm__ __volatile__(
          "   amswap_db.w  %0, %2, %1   \n"   /* _db 带内存屏障,更安全 */
          : "=&r"(ret), "+ZB"(*lock)
          : "r"((int)1)
          : "memory");
      return ret;
  }

  #define S_UNLOCK(lock)  \
      do { \
          __asm__ __volatile__("dbar 0 \n" ::: "memory");  /* 全屏障,确保前面的写都生效 */ \
          *((volatile slock_t *) (lock)) = 0; \
      } while (0)

  #endif /* __loongarch__ */

  6.2 原子操作 + 内存屏障 ——src/include/port/atomics/

  大白话:好消息是——现代GCC(≥8)对龙芯/ARM的原子操作有内置支持,PG
  有个"通用兜底实现"generic-gcc.h,直接用编译器内置的 __atomic_*,不用自己写汇编。

  只需在 src/include/port/atomics.h 里确保龙芯走通用路径(通常自动就走了),并在 c.h
  里确认内存屏障定义。如果要自己定义屏障,加这个:

  /* src/include/port/atomics/arch-loongarch.h(新建此 include,或并入 generic)*/

  /* 内存屏障:dbar 指令。0 = 全屏障 */
  #define pg_memory_barrier_impl()    __asm__ __volatile__ ("dbar 0" ::: "memory")
  #define pg_read_barrier_impl()      __asm__ __volatile__ ("dbar 0" ::: "memory")
  #define pg_write_barrier_impl()     __asm__ __volatile__ ("dbar 0" ::: "memory")

  /* 其余原子操作(CAS、fetch_add 等)全部交给编译器内置,
     即 generic-gcc.h 里的 __atomic_compare_exchange_n / __atomic_fetch_add,
     龙芯 GCC 已正确支持,无需手写汇编。 */

  然后在 atomics.h 顶部加引用:

  #elif defined(__loongarch__) || defined(__loongarch64)
  #include "port/atomics/arch-loongarch.h"

  ▎ 核心理念(最优方案):能让编译器内置 __atomic_* 干的活,绝不手写汇编。只有自旋锁 TAS 因为历史原因 PG
  ▎ 坚持用内联汇编,其余全走通用路径——这是最省事且最不容易出bug 的做法。

  6.3 CRC32C 硬件加速(ARM64 性能关键,强烈建议开)

  大白话:PG 每个数据页都要算校验和(CRC32C),ARM64 有专门的硬件指令,开了能快好几倍。PG 自带了实现
  src/port/pg_crc32c_armv8.c,只要 configure 时 -march 带了 +crc,它自动启用,无需改码。验证一下:

  # 编译后确认硬件 CRC 生效
  grep "USE_ARMV8_CRC32C" src/include/pg_config.h
  # 输出 #define USE_ARMV8_CRC32C 1 就对了

  # 龙芯没有专用 CRC 指令,自动走软件查表实现(pg_crc32c_sb8.c),无需处理

  ---
  七、第⑤⑥步:编译+ 回归测试验证

  # ===== 编译(用满所有核心)=====
  make -j$(nproc)          # 全量编译
  make -C contrib -j$(nproc)  # 编译扩展插件
  make install
  make -C contrib install

  # ===== 回归测试(最重要的验证!)=====
  # 这步跑通,说明移植在功能上没问题
  make check 2>&1 | tee regress.log
  # 看结果:All N tests passed 就成功
  # 失败的 case 会生成 regression.diffs,重点看排序、浮点、时区相关差异

  # ===== 大白话:常见失败原因 =====
  # 1. 浮点精度差异 →龙芯/ARM 的 IEEE 实现细微差别,通常无害
  # 2. 排序顺序不同 →ICU/locale 没装对,回去补 libicu
  # 3. 字节序 →PG 支持的国产芯片都是小端,一般没问题

  性能压测(用最好的工具 pgbench + sysbench)

  # 初始化测试库
  /opt/pg/16/bin/initdb -D /data/pgdata --locale=zh_CN.UTF-8
  /opt/pg/16/bin/pg_ctl -D /data/pgdata -l log start
  /opt/pg/16/bin/createdb bench

  # pgbench:PG 官方压测工具(最权威)
  /opt/pg/16/bin/pgbench -i -s 100 bench           # 装载 1000万行
  /opt/pg/16/bin/pgbench -c 64 -j 16 -T 300 -P 5 bench   # 64并发压5分钟

  # 关注 tps,对比 x86 基线。ARM64 调好参数后通常能到 x86 的 90%~110%

  国产环境专属调优(postgresql.conf 关键参数)

  # ARM64 核多但单核弱,针对性调优
  shared_buffers = 物理内存的25%
  huge_pages = try                  # ARM 大页收益明显,务必开
  effective_io_concurrency = 200    # 国产 NVMe SSD 调高
  max_worker_processes = CPU核数
  max_parallel_workers = CPU核数
  wal_compression = lz4             # 国产芯片 IO 常是瓶颈,压缩 WAL 划算

  ---
  八、第⑦步:打包成国产OS 能装的 RPM/DEB

  大白话:编译出来的二进制要做成"安装包",才能在客户的麒麟/统信上一键安装。

  # ===== 麒麟/openEuler 做 RPM =====
  # 用 fpm(最省事的打包神器,一行命令把目录变成 RPM)
  gem install fpm
  fpm -s dir -t rpm \
      -n kingbase-pg16 -v 16.2 \
      --iteration 1.kylin.aarch64 \
      -a aarch64 \
      -d "readline" -d "openssl-libs" -d "libicu" \
      --prefix=/opt/pg/16 \
      -C /opt/pg/16 .
  # 生成 kingbase-pg16-16.2-1.kylin.aarch64.rpm

  # 客户机安装
  rpm -ivh kingbase-pg16-16.2-1.kylin.aarch64.rpm

  ---
  九、兼容性改造(信创落地常被要求的"软适配")

  大白话:信创项目里,客户原来多半用 Oracle,要求 PG 内核"长得像 Oracle"。这块不改 CPU
  相关代码,而是装兼容扩展。最优选择:

  -- 1. Oracle 语法兼容:装 orafce(开源最成熟)
  CREATE EXTENSION orafce;
  -- 立刻就能用 Oracle 的函数:
  SELECT nvl(null, 'x'), sysdate, to_char(1234.5,'9999.99'), dual;

  -- 2. 国密算法(信创强制要求):用 pgcrypto + 国密版 openssl(tongsuo)
  CREATE EXTENSION pgcrypto;
  -- 编译时 --with-openssl 指向 tongsuo,即可支持 SM2/SM3/SM4

  如果是 openGauss/KingbaseES 这类已内置 Oracle 兼容模式的内核,建库时直接指定:

  -- KingbaseES / openGauss 建库时开 Oracle 兼容模式
  CREATE DATABASE oradb DBCOMPATIBILITY = 'A';   -- 'A'=Oracle, 'B'=MySQL, 'PG'=原生

  ---
  十、整套方案的"最优"判断(一张表收尾)

  ┌──────────────┬─────────────────────────────┬────────────────────────────┐
  │     环节     │          最优选择           │           为什么           │
  ├──────────────┼─────────────────────────────┼────────────────────────────┤
  │ 编译环境     │ Docker + 目标 OS 官方镜像   │ 隔离、可复现、glibc 不会错 │
  ├──────────────┼─────────────────────────────┼────────────────────────────┤
  │ ARM64 移植   │ 只调编译参数 +crc,不改源码 │ PG 原生支持 ARM64          │
  ├──────────────┼─────────────────────────────┼────────────────────────────┤
  │ 龙芯原子操作 │ 优先用编译器内置 __atomic_* │ 手写汇编易错,内置最稳     │
  ├──────────────┼─────────────────────────────┼────────────────────────────┤
  │ 国密加密     │ 铜锁 Tongsuo 替换 openssl   │ 唯一开源且通过认证的国密库 │
  ├──────────────┼─────────────────────────────┼────────────────────────────┤
  │ Oracle 兼容  │ orafce 扩展                 │ 开源最成熟,覆盖最广       │
  ├──────────────┼─────────────────────────────┼────────────────────────────┤
  │ 打包         │ fpm                         │ 一行命令出 RPM/DEB         │
  ├──────────────┼─────────────────────────────┼────────────────────────────┤
  │ 验证         │ make check + pgbench        │ PG 官方标准,最权威        │
  └──────────────┴─────────────────────────────┴────────────────────────────┘

  ---
  给你的下一步建议

  你现在卡在哪个具体环节,告诉我就能给更精准的代码:

  1. 你的目标 CPU 是哪个?(鲲鹏 ARM?龙芯?申威?)——决定要不要改汇编
  2. PG 内核是哪家的?(原生 PG / openGauss / KingbaseES / PolarDB)——决定补丁方式
  3. 目标操作系统 + 版本?(麒麟 V10 SP3?UOS?)——决定依赖包和 glibc

  把这三个告诉我,我直接给你那条路线的逐条命令 + 可能踩的具体报错和解法。

  要我现在就针对某一个具体组合(比如最常见的「鲲鹏 920 + 麒麟 V10 + 原生 PG16」)写一份从零到跑通的完整逐行实操脚本吗?

「鲲鹏 920 + 麒麟 V10 + 原生 PG16」

鲲鹏 920 + 麒麟 V10 + 原生 PG16 —— 从零到跑通完整实操

  这是信创最常见、也最顺的组合。鲲鹏 920 是 ARM64(aarch64),PG16 原生支持,不用改任何 C
  源码、不用写汇编,核心工作就是「正确的编译参数 + 凑齐依赖 + 调优」。

  下面每条命令都能直接复制执行,关键处都有大白话解释。

 ---0 步:先确认你的环境长这样(30 秒)

  uname -m                          # 必须输出 aarch64
  lscpu | grep -i "model name"      # 应含 Kunpeng-920
  cat /etc/kylin-release            # 看麒麟版本,如 V10 SP3
  ldd --version | head -1           # glibc 版本,麒麟V10 一般是 2.28
  gcc --version | head -1           # 麒麟V10 自带 gcc 7.3,够用
  grep -o 'crc32\|aes\|sha' /proc/cpuinfo | sort -u   # 确认有硬件加速指令

  ▎ 大白话:最后一条最关键。鲲鹏 920 必须能看到 crc32,这意味着可以开启硬件 CRC 加速,PG
  ▎ 校验和性能能快好几倍。看不到就说明 CPU 信息没读对,先别往下走。

  ---1 步:装齐编译依赖(麒麟 V10 用 yum)

  # 切到 root
  sudo -i

  # 麒麟V10 自带 yum 源就够,一行装齐 PG16 全部编译依赖
  yum install -y \
      gcc gcc-c++ make \
      flex bison \
      readline-devel zlib-devel \
      openssl-devel \
      libicu-devel \
      libxml2-devel libxslt-devel \
      perl-devel python3-devel tcl-devel \
      systemd-devel libuuid-devel \
      lz4-devel \
      perl-IPC-Run perl-Test-Harness   # 这两个是跑回归测试 make check 要用的

  逐个解释为什么要装:
  - flex bison ——PG 的 SQL 解析器要用它们生成,缺了编译直接报错
  - readline-devel ——psql 命令行的方向键/历史记录,没它体验极差
  - openssl-devel ——SSL 加密连接,信创基本都要求
  - libicu-devel ——中文排序的命根子,缺了中文 ORDER BY 会乱序
  - lz4-devel ——WAL 压缩,鲲鹏 IO 常是瓶颈,开了划算
  - systemd-devel ——让 PG 能注册成系统服务

  ▎ 避坑:如果 yum install 报某个包找不到,先 yum makecache 刷新缓存;麒麟有的版本 libuuid-devel 叫
  ▎ uuid-devel,二选一即可。

  ---2 步:下载 PG16 源码

  cd /usr/local/src

  # 官方源码(如果服务器能上外网)
  wget https://ftp.postgresql.org/pub/source/v16.2/postgresql-16.2.tar.bz2

  # 内网环境就先在能上网的机器下好,scp 传进来
  tar -xjf postgresql-16.2.tar.bz2
  cd postgresql-16.2

  ---3 步:configure ——鲲鹏 920 最优编译参数(核心!)

  这一步决定性能上限,鲲鹏专属参数全在这:

  # 关键:鲲鹏920的最优 CFLAGS
  export CFLAGS="-O2 -march=armv8-a+crc+crypto -mtune=tsv110 -fno-omit-frame-pointer"

  ./configure \
      --prefix=/opt/pgsql/16 \
      --with-icu \
      --with-openssl \
      --with-readline \
      --with-libxml \
      --with-libxslt \
      --with-lz4 \
      --with-uuid=e2fs \
      --with-systemd \
      --with-python \
      --enable-thread-safety \
      CFLAGS="$CFLAGS"

  逐个参数大白话:

  ┌───────────────────────────┬──────────────────────────────────────────────────────────────┐
  │           参数            │                            干嘛的                            │
  ├───────────────────────────┼──────────────────────────────────────────────────────────────┤
  │ -march=armv8-a+crc+crypto │ 告诉编译器用鲲鹏的硬件 CRC 和加密指令——性能关键,必须带+crc │
  ├───────────────────────────┼──────────────────────────────────────────────────────────────┤
  │ -mtune=tsv110             │ tsv110 是鲲鹏 920 的内核代号,针对它优化指令调度             │
  ├───────────────────────────┼──────────────────────────────────────────────────────────────┤
  │ -fno-omit-frame-pointer   │ 保留栈帧,将来用 perf 抓性能火焰图时能看到完整调用栈         │
  ├───────────────────────────┼──────────────────────────────────────────────────────────────┤
  │ --prefix=/opt/pgsql/16    │ 装到哪,建议带版本号方便以后多版本共存                       │
  ├───────────────────────────┼──────────────────────────────────────────────────────────────┤
  │ --with-icu                │ 开 ICU,中文排序正确                                         │
  ├───────────────────────────┼──────────────────────────────────────────────────────────────┤
  │ --with-systemd            │ 能用 systemctl 管理服务                                      │
  └───────────────────────────┴──────────────────────────────────────────────────────────────┘

  configure 跑完,验证 CRC 硬件加速有没有真的开启:

  grep -E "USE_ARMV8_CRC32C|USE_ICU" src/include/pg_config.h

  期望输出(看到这两行才算成功):
  #define USE_ARMV8_CRC32C 1      ←硬件 CRC 开了!
  #define USE_ICU 1               ←ICU 开了!

  ▎ 大白话:如果没看到 USE_ARMV8_CRC32C,说明 +crc 没生效,回去检查 CFLAGS。这是鲲鹏移植最值钱的一行优化。

  ---4 步:编译 + 安装

  # 用满所有核心编译(鲲鹏920核多,这步飞快)
  make -j$(nproc)

  # 编译 contrib 扩展(pgcrypto、orafce 依赖的基础设施等)
  make -j$(nproc) -C contrib

  # 安装
  make install
  make install -C contrib

  编译期间如果中途报错,看第 11 步的常见报错速查表。

  ---5 步:创建专用用户 + 初始化数据库

  大白话:数据库绝不能用 root 跑(安全红线),建个专用 postgres 用户。

  # 建用户和数据目录
  groupadd postgres
  useradd -g postgres -m postgres
  mkdir -p /data/pgdata
  chown -R postgres:postgres /data/pgdata /opt/pgsql

  # 配置 postgres 用户的环境变量
  cat >> /home/postgres/.bash_profile <<'EOF'
  export PGHOME=/opt/pgsql/16
  export PGDATA=/data/pgdata
  export PATH=$PGHOME/bin:$PATH
  export LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH
  export LANG=zh_CN.UTF-8
  EOF

  # 切到 postgres 用户初始化(注意:必须用普通用户)
  su - postgres
  source ~/.bash_profile

  # 初始化数据库,用 ICU 做默认排序(中文友好)
  initdb -D $PGDATA \
      --encoding=UTF8 \
      --locale-provider=icu \
      --icu-locale=zh-CN \
      --locale=zh_CN.UTF-8

  # 看到 "Success. You can now start..." 就成了

  ▎ 大白话:--locale-provider=icu --icu-locale=zh-CN 是 PG16 的新特性,让中文排序按拼音正确排,比老的 glibc locale
  ▎ 更稳。这是信创项目中文场景的最优配置。

  ---6 步:鲲鹏专属性能调优(postgresql.conf)

  大白话:鲲鹏 920 核多但单核主频不如 x86 高,所以策略是"靠并行取胜 + 把 IO 压住"。下面参数针对鲲鹏定制。

  # 还是 postgres 用户
  cat >> $PGDATA/postgresql.conf <<'EOF'

  # ============ 鲲鹏920 信创调优 ============
  listen_addresses = '*'
  port = 5432
  max_connections = 500

  # 内存(按物理内存调,这里假设 64G 机器)
  shared_buffers = 16GB                 # 物理内存 25%
  effective_cache_size = 48GB           # 物理内存 75%
  work_mem = 32MB
  maintenance_work_mem = 2GB

  # 大页:ARM 上收益明显,强烈建议开
  huge_pages = try

  # 并行:鲲鹏核多,把并行拉满
  max_worker_processes = 64             # = CPU 核数
  max_parallel_workers = 64
  max_parallel_workers_per_gather = 8
  max_parallel_maintenance_workers = 8

  # IO:国产 NVMe SSD 调高
  effective_io_concurrency = 200
  random_page_cost = 1.1                # SSD 用 1.1

  # WAL:鲲鹏 IO 常是瓶颈,开 lz4 压缩
  wal_compression = lz4
  wal_buffers = 64MB
  max_wal_size = 16GB
  min_wal_size = 4GB
  checkpoint_completion_target = 0.9

  # 日志
  logging_collector = on
  log_directory = 'log'
  log_filename = 'postgresql-%Y-%m-%d.log'
  log_min_duration_statement = 1000     # 记录超 1 秒的慢 SQL
  EOF

  配置访问权限(允许网段连接):

  cat >> $PGDATA/pg_hba.conf <<'EOF'
  # 允许内网网段用密码连接(按你实际网段改)
  host    all    all    192.168.0.0/16    scram-sha-256
  EOF

  ---7 步:注册成 systemd 服务(开机自启)

  # 回到 root
  exit   # 退出 postgres 用户

  cat > /etc/systemd/system/postgresql-16.service <<'EOF'
  [Unit]
  Description=PostgreSQL 16 database server
  After=network.target

  [Service]
  Type=notify
  User=postgres
  Group=postgres
  Environment=PGDATA=/data/pgdata
  ExecStart=/opt/pgsql/16/bin/postgres -D /data/pgdata
  ExecReload=/bin/kill -HUP $MAINPID
  KillMode=mixed
  KillSignal=SIGINT
  TimeoutSec=infinity
  OOMScoreAdjust=-1000

  [Install]
  WantedBy=multi-user.target
  EOF

  # 启用并启动
  systemctl daemon-reload
  systemctl enable postgresql-16
  systemctl start postgresql-16
  systemctl status postgresql-16     # 看到 active (running) 就成功

  开放防火墙端口:

  firewall-cmd --permanent --add-port=5432/tcp
  firewall-cmd --reload

  ---8 步:验证移植成功(功能 + 性能双验证)

  8.1 设密码 + 连接测试

  su - postgres
  psql -c "ALTER USER postgres PASSWORD 'YourStrongPwd@2026';"
  psql -c "SELECT version();"
  # 应输出:PostgreSQL 16.2 ... aarch64-... 看到 aarch64 说明确实是 ARM 版

  8.2 验证中文排序正确(信创必查)

  psql <<'EOF'
  CREATE TABLE t(n text);
  INSERT INTO t VALUES ('张三'),('李四'),('王五'),('赵六');
  SELECT n FROM t ORDER BY n;   -- 应按拼音排:李四、王五、张三、赵六
  EOF

  8.3 性能压测(pgbench,鲲鹏实测)

  createdb bench
  pgbench -i -s 100 bench                        # 装载约 1000 万行
  pgbench -c 64 -j 16 -T 120 -P 10 bench         # 64并发压2分钟,每10秒报一次

  # 关注输出的 tps 值。鲲鹏920 调好参数后,
  # 这套配置 64 并发只读 tps 通常能到 x86 同级机器的 90%~110%

  ---9 步(可选):Oracle 兼容 + 国密

  如果客户原来用 Oracle,装 orafce:

  # 先装 orafce(需要先 git clone 或下载源码)
  cd /usr/local/src
  git clone https://github.com/orafce/orafce.git
  cd orafce
  make USE_PGXS=1 PG_CONFIG=/opt/pgsql/16/bin/pg_config
  make USE_PGXS=1 PG_CONFIG=/opt/pgsql/16/bin/pg_config install

  # 在数据库里启用
  psql -d bench -c "CREATE EXTENSION orafce;"
  psql -d bench -c "SELECT sysdate, nvl(NULL,'默认值'), to_char(1234.5,'9999.99');"
  # 立刻能用 Oracle 的函数了

  ---10 步:打包成 RPM 给客户一键安装

  # root 
  gem install fpm   # 或 yum install rubygems 后再装

  fpm -s dir -t rpm \
      -n postgresql16-kunpeng -v 16.2 \
      --iteration 1.ky10.aarch64 \
      -a aarch64 \
      -d readline -d openssl-libs -d libicu -d lz4 \
      --prefix=/opt/pgsql/16 \
      -C /opt/pgsql/16 .

  # 生成 postgresql16-kunpeng-16.2-1.ky10.aarch64.rpm
  # 客户机直接:rpm -ivh xxx.rpm

  ▎ 关键避坑:打包机的 glibc 版本必须 ≤客户机。一定要在同款麒麟 V10 上编译打包,否则客户机会报 GLIBC_2.xx not found。

  ---11 步:鲲鹏常见报错速查表

  ┌──────────────────────────────────┬─────────────────────┬────────────────────────────────────────────────────────┐
  │               报错               │        原因         │                          解法                          │
  ├──────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────┤
  │ configure: error: readline       │ 没装 readline-devel │ yum install -y readline-devel                          │
  │ library not found                │                     │                                                        │
  ├──────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────┤
  │ pg_config.h 里没有               │ CFLAGS 漏了 +crc    │ 重新 configure,CFLAGS 加 -march=armv8-a+crc           │
  │ USE_ARMV8_CRC32C                 │                     │                                                        │
  ├──────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────┤
  │ make check 排序相关 case 失败    │ ICU/locale 没配对   │ 确认 --with-icu,重新 initdb 用 icu provider           │
  ├──────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────┤
  │ 启动报 huge_pages 失败           │ 系统没配大页        │ 改成 huge_pages = try(自动降级),或 sysctl -w        │
  │                                  │                     │ vm.nr_hugepages=8192                                   │
  ├──────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────┤
  │ GLIBC_2.34 not found             │ 编译机 glibc        │ 在麒麟V10原生环境重编,别用新系统编                    │
  │                                  │ 比客户机新          │                                                        │
  ├──────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────┤
  │ 中文显示乱码                     │ 客户端编码不对      │ export LANG=zh_CN.UTF-8 + \encoding UTF8               │
  └──────────────────────────────────┴─────────────────────┴────────────────────────────────────────────────────────┘

  ---
  整套流程一句话总结

  ▎ 鲲鹏 920 上移植原生 PG16,完全不用改 C 代码,成败就在两件事:
  ▎ 1. -march=armv8-a+crc+crypto 一定要带(验证 USE_ARMV8_CRC32C=1)——这是性能命根子;
  ▎ 2. 在麒麟 V10 原生环境里编译打包——这是部署不翻车的命根子。
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐