openGauss 常用运维指令手册
openGauss 常用运维指令手册
适用版本:openGauss 5.0 / 6.0 / 7.0.0 LTS(当前推荐) 约定:
#root 或 sudo,$omm 用户,postgres=#gsql 提示符,<xxx>为占位符。 差异标注:正文用> **版本差异**引用块标注跨版本不一致之处。 更新时间:2026-11
目录
- 版本与支持周期
- 架构与目录约定
- 下载与安装
- 集群部署(gs_preinstall / gs_install)
- 服务启停三层命令的分工
- gsql 客户端与连接认证
- 配置文件与参数
- 用户、角色与权限
- 库表对象与存储引擎
- 备份与恢复
- WAL、归档与 PITR
- 主备复制与 CM 集群管理
- 日志体系
- 性能诊断
- 空间、VACUUM 与膨胀
- 扩缩容、升级与迁移
- 高频故障速查
- 危险命令与避坑清单
- 附录:一键巡检脚本
1. 版本与支持周期
1.1 发布节奏
openGauss 由华为主导、开放原子开源基金会托管,采用「大版本 + 补丁」模式:每 2 年发一个大版本,社区提供 3 年维护支持,OGSP(openGauss 服务伙伴)可延长到 3 年以上。
| 版本 | 类型 | 维护截止 | 状态(2026-11) |
|---|---|---|---|
| 3.0.0 | LTS | 2026-03 | 已到期,建议升级 |
| 3.1.1 | 维护版 | — | 停止维护 |
| 5.0.0 | LTS | 2027-03 | 维护中 |
| 6.0.0 | LTS | 2028-09 | 维护中(6.0.6 为最新补丁) |
| 7.0.0 | LTS | 2029-09-30 | 当前推荐 |
与 PostgreSQL 的关系要说清楚:openGauss 早期基于 PostgreSQL 9.2 内核,但经过华为重写,不是 PG 的发行版。到了 5.0 之后,两者在存储引擎(UStore/AStore)、并发控制(CSN 事务)、执行器(向量化)、安全(全密态)上已经分道扬镳。 运维上的直接后果:不能用 PG 的
pg_ctl、psql、pg_dump去操作 openGauss,工具名前缀全部是gs_。
1.2 版本识别
# 二进制版本
gsql --version
gaussdb --version
# 集群版本(含补丁号)
gs_om -t status --detail
-- 数据库内版本
SELECT version();
SELECT * FROM pg_database_version(); -- 部分版本可用
-- 兼容模式(关键,决定 SQL 语法行为)
SHOW sql_compatibility;
1.3 四种兼容模式
sql_compatibility 在建库时指定,之后不能改:
| 取值 | 兼容 | 典型差异 |
|---|---|---|
A |
Oracle | 空串等于 NULL、DUAL 表、NVL、序列 NEXTVAL、大小写敏感 |
B |
MySQL | 反引号、LIMIT、AUTO_INCREMENT、IFNULL |
C |
Teradata | 特定分析函数语法 |
PG |
PostgreSQL | 标准 PG 行为,information_schema 完整 |
-- 建库时指定(推荐 A 或 B,按源库来)
CREATE DATABASE app_db WITH ENCODING='UTF8' DBCOMPATIBILITY='A';
-- 查询现有库的兼容模式
SELECT datname, datcompatibility FROM pg_database;
这是 openGauss 迁移的第一道坎:库建好之后
DBCOMPATIBILITY不可修改,选错了只能新建库重导。从 Oracle 迁就用A,从 MySQL 迁就用B,新建系统建议PG。
2. 架构与目录约定
2.1 进程模型
openGauss 是多线程架构(PG 是多进程),主进程 gaussdb 内部派生线程:
# 查看线程(不是进程)
ps -eLf | grep gaussdb | head -20
# 关键线程
# main 主线程
# pagewriter 脏页刷盘
# walwriter WAL 写盘
# checkpointer 检查点
# bgworker 后台任务
# gaussdb worker 并行执行
2.2 目录结构
| 路径 | 内容 |
|---|---|
/usr/local/opengauss($GAUSSHOME) |
数据库二进制、工具、插件 |
/usr/local/opengauss/data($PGDATA) |
数据目录、配置文件、WAL |
$PGDATA/postgresql.conf |
主配置 |
$PGDATA/pg_hba.conf |
客户端认证 |
$PGDATA/pg_ident.conf |
用户映射 |
$PGDATA/pg_xlog/ |
WAL 日志(注意仍叫 pg_xlog,不是 pg_wal) |
$PGDATA/base/ |
各数据库的物理文件 |
$PGDATA/pg_log/ |
运行日志(部分版本在 /var/log/omm/) |
/var/log/omm/ |
omm 用户的集群日志 |
# 确认环境变量(必须用 omm 用户)
su - omm
echo $GAUSSHOME
echo $PGDATA
echo $LD_LIBRARY_PATH # 必须包含 $GAUSSHOME/lib
切换用户必须
su - omm,不能su omm。后者不加载 profile,$GAUSSHOME/$LD_LIBRARY_PATH为空,所有gs_*命令都会报「找不到命令」或「找不到动态库」。
2.3 默认端口
| 服务 | 默认端口 | 说明 |
|---|---|---|
| 数据库 | 15400 | 不是 PG 的 5432,安装时也可指定 |
| CM(集群管理) | 由 cm_agent.ini 配置 |
3.0+ 引入 |
| 备机只读 | 与主机同端口 | 通过 hot_standby=on 提供只读 |
3. 下载与安装
3.1 官方入口
3.2 安装包类型
| 类型 | 适用 | 说明 |
|---|---|---|
| 企业版 | 生产集群 | 含 CM、OM、全套工具,需 gs_preinstall |
| 极简版 | 单机测试 | 解压即用,无 CM |
| 轻量版 | 容器/边缘 | 体积小,功能裁剪 |
| 企业版(noLSE) | 无 LSE 指令的 ARM | 鲲鹏早期芯片兼容 |
| Docker | 开发测试 | opengauss/opengauss:7.0.0 |
# Docker 快速体验
docker pull opengauss/opengauss:7.0.0
docker run -d --name opengauss --privileged=true \
-e GS_PASSWORD='Enmo@123' \
-p 15400:5432 \
-v /data/opengauss:/var/lib/opengauss \
opengauss/opengauss:7.0.0
# 连接(容器内默认端口 5432,映射到宿主机 15400)
gsql -d postgres -h 127.0.0.1 -p 15400 -U gaussdb -W 'Enmo@123'
官方镜像里数据库端口是 5432,映射出来才看到 15400。别拿镜像的行为去推断裸机安装的端口。
3.3 环境准备
# 1) 创建用户组与用户
groupadd dbgrp
useradd -g dbgrp -m -d /home/omm omm
echo 'omm@123' | passwd --stdin omm
# 2) 目录与权限
mkdir -p /usr/local/opengauss /var/log/omm /opt/software/openGauss
chown -R omm:dbgrp /usr/local/opengauss /var/log/omm
# 3) 内核参数
cat >> /etc/sysctl.conf <<'EOF'
kernel.shmall = 4294967296
kernel.shmmax = 68719476736
kernel.shmmni = 4096
kernel.sem = 50100 64128000 50100 1280
fs.file-max = 7672460
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576
EOF
sysctl -p
# 4) 资源限制(omm 用户)
cat >> /etc/security/limits.conf <<'EOF'
omm soft nofile 1000000
omm hard nofile 1000000
omm soft nproc 1000000
omm hard nproc 1000000
omm soft stack unlimited
omm hard stack unlimited
omm soft memlock unlimited
omm hard memlock unlimited
EOF
# 5) 关闭 SELinux / 防火墙(或放行端口)
setenforce 0
systemctl stop firewalld
# 6) 关闭 swap(可选,但强烈建议)
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
# 7) 时间同步
systemctl enable --now chronyd
chronyc sources
3.4 解压与预安装
# 解压安装包(root)
cd /opt/software/openGauss
tar xzf openGauss-7.0.0-openEuler-64bit-all.tar.gz
tar xzf openGauss-7.0.0-openEuler-64bit-om.tar.gz
# 预安装(root 执行,准备目录、权限、环境变量、SSH 互信)
cd /opt/software/openGauss/script
./gs_preinstall -U omm -G dbgrp -X /opt/software/openGauss/cluster_config.xml
# 预安装成功标志
# Successfully set finish flag.
# Preinstallation succeeded.
预安装会做这些事:建目录、改权限、写环境变量到 /etc/profile.d/、配置 omm 用户互信、检查依赖。预安装失败几乎都是权限或 SSH 互信问题。
# 手动配置互信(预安装失败时补救)
su - omm
gs_ssh -c "date" # 能通说明互信 OK
4. 集群部署(gs_preinstall / gs_install)
4.1 集群配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
<CLUSTER>
<PARAM name="clusterName" value="og_primary"/>
<PARAM name="nodeNames" value="og-node1,og-node2"/>
<PARAM name="gaussdbAppPath" value="/usr/local/opengauss/app"/>
<PARAM name="gaussdbLogPath" value="/var/log/omm"/>
<PARAM name="tmpMppdbPath" value="/opt/omm/tmp"/>
<PARAM name="gaussdbToolPath" value="/usr/local/opengauss/tool"/>
<PARAM name="corePath" value="/opt/omm/corefile"/>
<PARAM name="backIp1s" value="10.0.0.11,10.0.0.12"/>
</CLUSTER>
<DEVICELIST>
<DEVICE sn="og-node1">
<PARAM name="name" value="og-node1"/>
<PARAM name="azName" value="AZ1"/>
<PARAM name="azPriority" value="1"/>
<PARAM name="backIp1" value="10.0.0.11"/>
<PARAM name="sshIp1" value="10.0.0.11"/>
<PARAM name="dataNum" value="1"/>
<PARAM name="dataPortBase" value="15400"/>
<PARAM name="dataNode1" value="/usr/local/opengauss/data,og-node2,/usr/local/opengauss/data"/>
</DEVICE>
<DEVICE sn="og-node2">
<PARAM name="name" value="og-node2"/>
<PARAM name="azName" value="AZ1"/>
<PARAM name="azPriority" value="1"/>
<PARAM name="backIp1" value="10.0.0.12"/>
<PARAM name="sshIp1" value="10.0.0.12"/>
</DEVICE>
</DEVICELIST>
</ROOT>
| 参数 | 说明 |
|---|---|
clusterName |
集群名,会成为 systemd 服务名 opengauss-<clusterName> |
dataPortBase |
基础端口,主库 15400,备库自动 +1 |
dataNode1 |
数据目录与备机列表,格式 主机目录,备机1,备机1目录,... |
backIp1s |
所有节点业务 IP,逗号分隔 |
dataNode1里主机目录在前,后面两两一组(备机名, 备机目录)。写错会导致备机数据目录冲突,安装直接失败。
4.2 安装
# 切到 omm 用户执行
su - omm
cd /opt/software/openGauss/script
gs_install -X /opt/software/openGauss/cluster_config.xml \
--gsinit-parameter="--encoding=UTF8" \
--dn-guc="max_connections=3000" \
--dn-guc="shared_buffers=8GB" \
--dn-guc="password_encryption_type=2"
# 安装过程会提示设置数据库初始密码(需满足复杂度:8位以上,含3类字符)
# 安装后检查
gs_om -t status --detail
gsql -d postgres -p 15400 -r
4.3 卸载
# 停止集群
gs_om -t stop
# 卸载(omm 用户)
gs_uninstall --delete-data
# 清理环境(root)
cd /opt/software/openGauss/script
./gs_postuninstall -U omm -G dbgrp -X cluster_config.xml
5. 服务启停三层命令的分工
openGauss 有三套启停命令,搞混是新手最大的痛点。记住分工:
| 命令 | 层级 | 适用场景 |
|---|---|---|
gs_om |
集群级(OM 工具) | 整套集群启停、状态查询、主备切换 |
cm_ctl |
集群级(CM 组件) | 3.0+ 装了 CM 后的标准方式,支持自动故障切换 |
gs_ctl |
单实例级 | 单节点启停、备机重建、单点排查 |
5.1 gs_om(最常用)
# 状态
gs_om -t status
gs_om -t status --detail
gs_om -t status --all
# 启停(整个集群)
gs_om -t start
gs_om -t stop
gs_om -t restart
# 只启停某节点
gs_om -t start -h og-node2
gs_om -t stop -h og-node2
# 主备切换
gs_om -t switch --instance og-node1
gs_om -t switchover
# 备机升主(主机故障时)
gs_om -t failover
# 刷新 ETCD(CM 模式下改了配置后)
gs_om -t refreshconf
# 重建 CM 配置文件
gs_om -t generate-config
# 查看集群静态配置
gs_om -t view
5.2 cm_ctl(装了 CM 后)
# 状态
cm_ctl query -Cv
cm_ctl query -Cvd
# 启停
cm_ctl start
cm_ctl stop
cm_ctl stop -n 1 -D /usr/local/opengauss/data # 停指定节点
cm_ctl start -n 2
# 主备切换
cm_ctl switchover -n 1 -D /usr/local/opengauss/data
cm_ctl switchover -a # 自动选主
# 备机重建
cm_ctl build -n 2 -D /usr/local/opengauss/data -b full
# 查看 CM 集群状态
cm_ctl query -Cv -i all
CM 模式下不要用
gs_om -t stop。CM 会检测到实例退出并自动拉起,表现为「停了又起来」。要用cm_ctl stop,它会同时停 CM 和实例。
5.3 gs_ctl(单实例)
# 启停
gs_ctl start -D $PGDATA
gs_ctl stop -D $PGDATA -m fast
gs_ctl restart -D $PGDATA
gs_ctl status -D $PGDATA
# 停止模式
# smart 等所有连接断开(可能永远停不下来)
# fast 断开连接、回滚事务(推荐)
# immediate 立即退出,重启需要恢复(最后手段)
# 查询主备状态
gs_ctl query -D $PGDATA
# 备机重建(全量)
gs_ctl build -D $PGDATA -b full
# 备机重建(增量)
gs_ctl build -D $PGDATA -b incremental
# 备机升主
gs_ctl failover -D $PGDATA
# 主备切换
gs_ctl switchover -D $PGDATA
# 通知 CM 当前角色(CM 模式下改角色后必须执行)
gs_ctl notify -D $PGDATA -M primary
gs_ctl notify -D $PGDATA -M standby
# 重新加载配置
gs_ctl reload -D $PGDATA
# gs_ctl query 输出关键字段
# db_state Primary / Standby / Need repair
# sender_sent_location 主机已发送位点
# sender_replay_location 备机已接收位点
# receiver_received_location 备机已接收
# receiver_replayed_location 备机已回放
# 四个位点一致 = 无延迟
5.4 正确的停机顺序
# 集群停机(CM 模式)
cm_ctl stop
# 集群停机(非 CM 模式)
gs_om -t stop
# 单节点维护(先切主,再停)
gs_om -t switch --instance og-node1
gs_ctl stop -D $PGDATA -m fast
禁止直接
kill -9 gaussdb。会导致共享内存未释放、WAL 未刷盘,重启时要走崩溃恢复(可能几分钟到几十分钟)。
6. gsql 客户端与连接认证
6.1 连接
# 本机
gsql -d postgres -p 15400 -r
# 远程
gsql -h 10.0.0.11 -p 15400 -d postgres -U omm -W 'Password@123'
# 执行单条
gsql -d postgres -p 15400 -c "SELECT version();"
# 执行文件
gsql -d app_db -p 15400 -f /tmp/init.sql
# 指定输出格式
gsql -d app_db -p 15400 -A -F $'\t' -c "SELECT * FROM t1" # 无对齐、Tab 分隔
6.2 常用元命令
\l -- 列出数据库
\c app_db -- 切换数据库
\dn -- 列出 schema
\dt -- 列出表
\dt+ app_db.* -- 带大小
\d+ orders -- 表结构详情(含存储分布)
\di -- 索引
\dv -- 视图
\df -- 函数
\du -- 用户/角色
\dp -- 权限
\x -- 行转列显示(宽表必用)
\timing on -- 显示执行时间
\encoding -- 字符集
\pset pager off -- 关闭分页
\o /tmp/out.txt -- 输出重定向
\i /tmp/script.sql -- 执行文件
\q -- 退出
6.3 认证配置
# pg_hba.conf 典型配置
# TYPE DATABASE USER ADDRESS METHOD
local all all trust
host all all 127.0.0.1/32 sha256
host all all 10.0.0.0/24 sha256
host app_db app 10.0.1.0/24 sha256
# 改完 reload
gs_ctl reload -D $PGDATA
# 或
gs_guc reload -N all -I all -c "listen_addresses='0.0.0.0'"
| 认证方式 | 说明 |
|---|---|
trust |
免密(仅本机/测试) |
sha256 |
openGauss 默认,推荐 |
md5 |
兼容旧客户端 |
sm3 |
国密,需开启 |
cert |
证书认证 |
reject |
拒绝 |
password_encryption_type决定密码存储算法:1=md5,2=sha256(默认),3=sm3。改成2后旧 md5 密码用户需重置密码。这是从老版本升级后「密码突然不对」的原因。
6.4 连接数管理
-- 当前连接
SELECT datname, usename, client_addr, state, backend_start,
now() - state_change AS duration
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY duration DESC;
-- 按用户统计
SELECT usename, COUNT(*) FROM pg_stat_activity GROUP BY usename ORDER BY 2 DESC;
-- 最大连接数
SHOW max_connections;
SHOW max_process_memory;
-- 断开会话
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid = 12345;
-- 批量断开某用户
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE usename = 'app' AND state = 'idle' AND state_change < now() - interval '1 hour';
7. 配置文件与参数
7.1 修改方式
# 方式一:gs_guc(推荐,会做合法性校验)
gs_guc set -N all -I all -c "max_connections=3000"
gs_guc reload -N all -I all -c "work_mem=64MB"
gs_guc check -N all -I all -c "max_connections"
# 方式二:直接改 postgresql.conf(需 reload/restart)
vi $PGDATA/postgresql.conf
gs_ctl reload -D $PGDATA
| 参数 | 说明 |
|---|---|
-N all |
所有节点(也可 -N og-node1) |
-I all |
该节点所有实例 |
-c |
设置配置项 |
--values |
值文件 |
set |
需重启生效的参数 |
reload |
可动态加载的参数 |
set与reload用错会出问题:reload对需要重启的参数只是写入文件但不生效,命令不报错,容易误判「改了没效果」。不确定就用set(会重启实例,但一定生效)。
7.2 关键参数
| 参数 | 默认 | 建议 | 说明 |
|---|---|---|---|
max_connections |
200 | 1000~3000 | 每连接约占用 work_mem 级别内存 |
shared_buffers |
128MB | 物理内存 25%~40% | 共享缓冲池 |
work_mem |
4MB | 16~64MB | 单算子排序/哈希内存 |
maintenance_work_mem |
64MB | 512MB~2GB | VACUUM/CREATE INDEX 用 |
max_process_memory |
12GB | 物理内存 60%~70% | openGauss 特有,进程总内存上限 |
cstore_buffers |
32MB | 512MB~4GB | 列存缓冲 |
wal_level |
hot_standby | logical(需逻辑复制) |
WAL 级别 |
max_wal_size |
1GB | 4~16GB | 触发检查点的 WAL 量 |
checkpoint_timeout |
15min | 15~30min | 检查点间隔 |
archive_mode |
off | on | 归档开关 |
archive_command |
— | cp %p /archive/%f |
归档命令 |
synchronous_commit |
on | on(金融)/ off(可容忍丢数据) | 同步提交 |
recovery_time_target |
0 | 60~300 | openGauss 特有,备机回放延迟目标(秒) |
enable_thread_pool |
off | on(高并发) | 线程池模式,显著降内存 |
max_threads_per_session |
8 | 8~16 | 线程池下每会话线程数 |
log_min_duration_statement |
-1 | 1000(ms) | 慢 SQL 阈值 |
log_statement |
none | ddl |
记录 DDL |
password_encryption_type |
2 | 2 | 密码算法 |
-- 查看参数
SHOW shared_buffers;
SELECT name, setting, unit, context FROM pg_settings WHERE name IN
('max_connections','shared_buffers','work_mem','max_process_memory','enable_thread_pool');
-- 会话级临时改
SET work_mem = '128MB';
SET statement_timeout = '30s';
max_process_memory是 openGauss 的「总闸」,超过会直接 OOM kill。它必须大于shared_buffers + cstore_buffers + max_connections × (work_mem × 每查询算子数)。这是 openGauss 最常见的 OOM 根因,调参时优先算这个。
7.3 向量化与并行
-- 并行度
SHOW query_dop; -- 0 = 自适应
SET query_dop = 4;
-- 向量化执行(默认开启,不建议关)
SHOW enable_vectorized_engine;
8. 用户、角色与权限
8.1 用户与角色
-- 建用户(密码需满足复杂度:≥8位,含大写/小写/数字/特殊字符中至少3类)
CREATE USER app WITH PASSWORD 'App@12345';
-- 建角色
CREATE ROLE read_only WITH LOGIN PASSWORD 'Ro@123456';
-- 用户即角色(openGauss 中 USER 是带 LOGIN 的 ROLE)
CREATE ROLE dba_role;
GRANT dba_role TO app;
-- 改密(普通用户改自己)
ALTER USER app IDENTIFIED BY 'New@12345' REPLACE 'App@12345';
-- 管理员改他人密码
ALTER USER app IDENTIFIED BY 'New@12345';
-- 锁定/解锁
ALTER USER app ACCOUNT LOCK;
ALTER USER app ACCOUNT UNLOCK;
-- 有效期
ALTER USER app VALID BEGIN '2026-01-01' VALID UNTIL '2027-01-01';
-- 查看
SELECT usename, usesysid, usecreatedb, usesuper, userepl, valuntil
FROM pg_user;
-- 删除(有对象时需先转移或 CASCADE)
DROP USER app;
DROP USER app CASCADE;
8.2 权限模型
-- 库级
GRANT CONNECT ON DATABASE app_db TO app;
GRANT CREATE ON DATABASE app_db TO app;
REVOKE CONNECT ON DATABASE app_db FROM PUBLIC;
-- Schema 级(openGauss 必做,默认 public 权限收紧)
GRANT USAGE ON SCHEMA public TO app;
GRANT CREATE ON SCHEMA public TO app;
-- 表级
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app;
GRANT SELECT ON app_db.public.orders TO read_only;
-- 序列
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app;
-- 函数
GRANT EXECUTE ON FUNCTION fn_calc(int) TO app;
-- 默认权限(新建对象自动授权,非常重要)
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO read_only;
-- 查看权限
\dp app_db.public.orders
SELECT * FROM information_schema.table_privileges WHERE grantee = 'app';
8.3 三权分立
openGauss 支持安全管理员、审计管理员、系统管理员三权分立(等保要求):
-- 开启三权分立(需重启)
gs_guc set -N all -I all -c "enableSeparationOfDuty=on"
-- 创建三类管理员
CREATE USER sysadmin WITH SYSADMIN PASSWORD 'Sys@12345';
CREATE USER secadmin WITH CREATEROLE PASSWORD 'Sec@12345' AUDITADMIN;
CREATE USER auditor WITH AUDITADMIN PASSWORD 'Aud@12345';
| 角色 | 权限 |
|---|---|
SYSADMIN |
系统管理,不能审计、不能建用户 |
CREATEROLE |
建用户/角色,不能操作数据 |
AUDITADMIN |
审计日志查看与策略管理 |
MONADMIN |
监控视图访问 |
OPRADMIN |
运维操作(需配合 enable_thread_pool) |
POLADMIN |
行级访问控制策略 |
8.4 行级安全与脱敏
-- 行级访问控制(RLS)
CREATE ROW LEVEL SECURITY POLICY pol_orders ON orders
USING (user_id = current_user_id());
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- 数据脱敏策略
CREATE MASKING POLICY mask_phone AS (maskall(phone))
APPLY TO app;
-- 查看
SELECT * FROM gs_my_policies;
行级安全与脱敏是 openGauss 相对 PG 的强项,也是等保/密评项目里的常见要求。策略创建后必须
ENABLE ROW LEVEL SECURITY才生效,漏这一步是最常见的「配了没用」。
9. 库表对象与存储引擎
9.1 建库建表
CREATE DATABASE app_db
WITH ENCODING='UTF8'
DBCOMPATIBILITY='A'
TEMPLATE=template0
CONNECTION LIMIT=500;
\c app_db
-- 行存表(默认 AStore)
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
order_no VARCHAR(32) NOT NULL UNIQUE,
user_id BIGINT NOT NULL,
amount NUMERIC(18,2) NOT NULL,
status SMALLINT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- UStore 表(回滚段独立,适合高并发更新)
CREATE TABLE sessions (
id BIGSERIAL PRIMARY KEY,
data TEXT,
updated_at TIMESTAMP DEFAULT now()
) WITH (STORAGE_TYPE=USTORE);
-- 列存表(分析场景)
CREATE TABLE sales_fact (
sale_date DATE,
region VARCHAR(32),
amount NUMERIC(18,2)
) WITH (ORIENTATION=COLUMN);
-- 分区表
CREATE TABLE logs (
id BIGSERIAL,
log_time TIMESTAMP NOT NULL,
msg TEXT
) PARTITION BY RANGE (log_time);
CREATE TABLE logs_p202611 PARTITION OF logs
FOR VALUES FROM ('2026-11-01') TO ('2026-12-01');
| 存储引擎 | 特点 | 适用 |
|---|---|---|
| AStore | 追加写,回滚段在表空间,垃圾回收靠 VACUUM | OLTP 为主,默认 |
| UStore | 原地更新,回滚段独立(undo),空间膨胀小 | 高频 UPDATE,长事务 |
| 列存(COLUMN) | 列式压缩,向量化扫描快 | OLAP、宽表聚合 |
| MOT | 全内存,无锁并发 | 极高性能点查(需单独配置) |
AStore vs UStore 的选择:业务以 INSERT + 查询为主,用 AStore;业务有大量 UPDATE 且表很宽,用 UStore(避免 AStore 的「更新即新版本」导致膨胀)。UStore 在 3.0 后趋于稳定,但不支持部分特性(如逻辑解码的部分场景),选型前要核对。
9.2 索引
CREATE INDEX idx_orders_user ON orders(user_id);
CREATE INDEX idx_orders_user_time ON orders(user_id, created_at DESC);
CREATE UNIQUE INDEX uk_order_no ON orders(order_no);
-- 部分索引
CREATE INDEX idx_orders_pending ON orders(created_at) WHERE status = 0;
-- 表达式索引
CREATE INDEX idx_orders_month ON orders(EXTRACT(MONTH FROM created_at));
-- 并行建索引
SET query_dop = 4;
CREATE INDEX CONCURRENTLY idx_big ON big_table(col); -- 不锁表(部分版本支持)
-- 查看索引使用情况
SELECT indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes WHERE relname = 'orders' ORDER BY idx_scan;
-- 找无用索引(idx_scan = 0 且运行时间够长)
SELECT indexrelname, pg_size_pretty(pg_relation_size(indexrelid))
FROM pg_stat_user_indexes WHERE idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;
-- 删除
DROP INDEX idx_orders_month;
9.3 序列与自增
-- openGauss 支持 SERIAL / BIGSERIAL,也支持 Oracle 风格 SEQUENCE
CREATE SEQUENCE seq_order START 1 INCREMENT 1 CACHE 20;
SELECT nextval('seq_order');
SELECT currval('seq_order');
-- 查看序列当前值
SELECT last_value, is_called FROM seq_order;
-- 重置
ALTER SEQUENCE seq_order RESTART WITH 100000;
9.4 物化视图
CREATE MATERIALIZED VIEW mv_daily_sales AS
SELECT date_trunc('day', created_at) d, SUM(amount) total
FROM orders GROUP BY 1;
-- 刷新(会锁表,用 CONCURRENTLY 需有唯一索引)
REFRESH MATERIALIZED VIEW mv_daily_sales;
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_sales;
10. 备份与恢复
10.1 方案选型
| 方案 | 类型 | 速度 | 一致性 | 适用 |
|---|---|---|---|---|
gs_dump |
逻辑,单库 | 中 | 快照一致 | 单库迁移、小库 |
gs_dumpall |
逻辑,全实例 | 慢 | 一般 | 全实例迁移 |
gs_basebackup |
物理,全量 | 快 | 强一致 | 备机搭建、全量备份 |
gs_probackup |
物理,全量+增量 | 快 | 强一致 | 生产首选 |
| 文件系统快照 | 物理 | 极快 | 需停库或冻结 | 大库、有存储快照能力 |
10.2 逻辑备份
# 单库,纯文本
gs_dump -U omm -W 'xxx' -p 15400 -f /backup/app_db_20261105.sql app_db
# 单库,自定义格式(支持选择性恢复)
gs_dump -U omm -W 'xxx' -p 15400 -Fc -f /backup/app_db.dmp app_db
# 只导结构
gs_dump -U omm -W 'xxx' -p 15400 -s -f /backup/app_db_schema.sql app_db
# 只导数据
gs_dump -U omm -W 'xxx' -p 15400 -a -f /backup/app_db_data.sql app_db
# 只导某张表
gs_dump -U omm -W 'xxx' -p 15400 -t public.orders -f /backup/orders.sql app_db
# 并行导出(大库提速)
gs_dump -U omm -W 'xxx' -p 15400 -Fd -j 8 -f /backup/app_db_dir app_db
# 全实例
gs_dumpall -U omm -W 'xxx' -p 15400 -f /backup/all_20261105.sql
| 参数 | 说明 |
|---|---|
-Fp |
纯文本 SQL(默认) |
-Fc |
自定义格式,压缩,支持 gs_restore -l 选择性恢复 |
-Fd |
目录格式,必须配合 -j 并行 |
-Ft |
tar 格式 |
-j N |
并行度,仅 -Fd 有效 |
-s / -a |
只结构 / 只数据 |
-t |
指定表 |
-n |
指定 schema |
# 恢复
gs_restore -U omm -W 'xxx' -p 15400 -d app_db_new /backup/app_db.dmp
# 先看备份里有什么
gs_restore -l /backup/app_db.dmp
# 只恢复某张表
gs_restore -U omm -W 'xxx' -p 15400 -d app_db_new -t orders /backup/app_db.dmp
# 恢复到已有库(先删再建,-c 会 DROP)
gs_restore -U omm -W 'xxx' -p 15400 -d app_db -c /backup/app_db.dmp
# 并行恢复
gs_restore -U omm -W 'xxx' -p 15400 -d app_db_new -j 8 /backup/app_db_dir
10.3 物理备份(gs_basebackup)
# 全量物理备份(需有复制权限)
gs_basebackup -D /backup/base_20261105 -h 10.0.0.11 -p 15400 -U omm -W 'xxx' -Fp -Xs -P -R
# 参数说明
# -D 目标目录
# -Fp 普通文件格式(-Ft 为 tar)
# -Xs 流式传输 WAL
# -P 显示进度
# -R 自动生成 recovery.conf(用于搭备机)
10.4 gs_probackup(生产推荐)
# 1) 初始化备份目录
gs_probackup init -B /backup/probackup
# 2) 添加实例
gs_probackup add-instance -B /backup/probackup -D $PGDATA --instance=og1
# 3) 配置(可选,写入 pg_probackup.conf)
gs_probackup set-config -B /backup/probackup --instance=og1 \
--pgdata=$PGDATA \
--remote-proto=ssh --remote-host=10.0.0.11 --remote-user=omm
# 4) 全量备份
gs_probackup backup -B /backup/probackup --instance=og1 -b full \
--stream -j 8 --compress
# 5) 增量备份
gs_probackup backup -B /backup/probackup --instance=og1 -b incremental \
--stream -j 8 --compress
# 6) 查看备份列表
gs_probackup show -B /backup/probackup --instance=og1
# 7) 校验备份
gs_probackup validate -B /backup/probackup --instance=og1
# 8) 恢复(需先停库)
gs_ctl stop -D $PGDATA -m fast
gs_probackup restore -B /backup/probackup --instance=og1 -i <backup-id> -D $PGDATA
# 9) 恢复到时间点
gs_probackup restore -B /backup/probackup --instance=og1 -i <backup-id> \
-D $PGDATA --recovery-target-time='2026-11-05 09:30:00'
# 10) 清理旧备份(保留 7 天)
gs_probackup delete -B /backup/probackup --instance=og1 --retention-redundancy=7
gs_probackup的增量备份依赖 WAL 归档。如果archive_mode=off,增量备份会失败或退化为全量。生产必须先把归档配好。
10.5 备份策略
| 对象 | 频率 | 保留 | 说明 |
|---|---|---|---|
| 全量物理 | 每天 1 次 | 7 天 | gs_probackup -b full |
| 增量物理 | 每 6 小时 | 3 天 | 依赖 WAL 归档 |
| 逻辑备份 | 每周 1 次 | 30 天 | 跨版本迁移兜底 |
| WAL 归档 | 持续 | 7 天 | PITR 基础 |
11. WAL、归档与 PITR
11.1 开启归档
# 1) 建归档目录
mkdir -p /archive/og
chown -R omm:dbgrp /archive/og
# 2) 配置参数(主库)
gs_guc set -N all -I all -c "archive_mode=on"
gs_guc set -N all -I all -c "archive_command='cp %p /archive/og/%f'"
gs_guc set -N all -I all -c "wal_level=hot_standby"
# 3) 重启生效
gs_om -t restart
# 4) 验证(手动切一个 WAL)
gsql -d postgres -p 15400 -c "SELECT pg_switch_xlog();"
ls -lt /archive/og | head
openGauss 仍然用
pg_switch_xlog()/pg_xlogfile_name()这套旧命名(PG 10 之后已改为pg_switch_wal)。写脚本时不要照抄 PG 文档。
11.2 WAL 状态查询
-- 当前 WAL 位点
SELECT pg_current_xlog_location();
SELECT pg_current_xlog_insert_location();
-- 备机接收/回放位点
SELECT pg_last_xlog_receive_location();
SELECT pg_last_xlog_replay_location();
-- 延迟(字节)
SELECT pg_xlog_location_diff(pg_current_xlog_location(), pg_last_xlog_replay_location()) AS lag_bytes;
-- WAL 文件列表
SELECT * FROM pg_ls_dir('pg_xlog') WHERE pg_ls_dir ~ '^[0-9A-F]{24}$' ORDER BY 1 DESC LIMIT 10;
-- 归档状态
SELECT archived_count, failed_count, last_archived_wal, last_failed_wal
FROM pg_stat_archiver;
11.3 PITR 完整流程
# 1) 确认有基础备份 + 连续归档
gs_probackup show -B /backup/probackup --instance=og1
ls /archive/og | wc -l
# 2) 停止数据库
gs_om -t stop
# 3) 清空数据目录(先备份原目录!)
mv $PGDATA $PGDATA.bak_$(date +%F)
mkdir -p $PGDATA && chown omm:dbgrp $PGDATA && chmod 700 $PGDATA
# 4) 恢复基础备份
gs_probackup restore -B /backup/probackup --instance=og1 -i <backup-id> -D $PGDATA
# 5) 配恢复目标
cat >> $PGDATA/postgresql.conf <<'EOF'
restore_command = 'cp /archive/og/%f %p'
recovery_target_time = '2026-11-05 09:30:00'
recovery_target_action = 'promote'
EOF
# 6) 创建恢复标记
touch $PGDATA/recovery.signal
# 7) 启动(会自动回放 WAL 到目标时间后升主)
gs_ctl start -D $PGDATA
# 8) 验证
gsql -d postgres -p 15400 -c "SELECT now(), pg_is_in_recovery();"
recovery_target_action三个取值:pause(回放到目标点暂停,可检查后再 promote)、promote(直接升主)、shutdown(回放完关机)。生产建议pause,确认数据无误再gs_ctl notify -M primary。
11.4 归档失败处理
-- 查看失败的 WAL
SELECT last_failed_wal, last_failed_time FROM pg_stat_archiver;
-- 常见原因
-- 归档目录满 → df -h
-- 权限不对 → ls -ld /archive/og
-- archive_command 路径写错 → 手动执行一次验证
# 手动补归档(把 pg_xlog 里未归档的文件拷过去)
for f in $(ls $PGDATA/pg_xlog | grep -E '^[0-9A-F]{24}$'); do
[ -f /archive/og/$f ] || cp $PGDATA/pg_xlog/$f /archive/og/
done
归档断了会导致 PITR 出现断档,必须尽快补上。补完后
pg_stat_archiver的failed_count不会归零(历史累计),要看last_failed_wal是否还在推进。
12. 主备复制与 CM 集群管理
12.1 复制状态
-- 主库看备机
SELECT client_addr, state, sync_state,
sent_location, write_location, flush_location, replay_location,
pg_xlog_location_diff(pg_current_xlog_location(), replay_location) AS lag_bytes
FROM pg_stat_replication;
-- sync_state: async / potential / sync / quorum
# gs_ctl 看(更直观)
gs_ctl query -D $PGDATA
12.2 主备切换
# 计划内切换(原主变备,原备变主)
gs_om -t switch --instance og-node2
# 或
cm_ctl switchover -n 2 -D /usr/local/opengauss/data
# 故障切换(原主已挂,强制备机升主)
gs_om -t failover
# 或
gs_ctl failover -D $PGDATA
# 切换后确认
gs_om -t status --detail
gs_ctl query -D $PGDATA
switchover与failover的区别:
switchover:原主还活着,先追平再切,不丢数据,可回切;failover:原主已不可用,强制升主,可能丢最后一段 WAL,原主恢复后需要重建。 生产能switchover就不要failover。
12.3 备机重建
备机 db_state 变成 Need repair 时,必须重建:
# 1) 停备机
gs_ctl stop -D $PGDATA -m fast
# 2) 全量重建(推荐)
gs_ctl build -D $PGDATA -b full
# 3) 增量重建(数据量大时更快,但要求 WAL 完整)
gs_ctl build -D $PGDATA -b incremental
# 4) CM 模式
cm_ctl build -n 2 -D /usr/local/opengauss/data -b full
# 5) 验证
gs_ctl query -D $PGDATA
-- 判断是否需要重建
-- db_state = Need repair → 必须重建
-- 四个位点差距持续增大 → 先查网络/磁盘,不一定要重建
12.4 同步复制配置
# 单备同步(一主一备强一致)
gs_guc set -N all -I all -c "synchronous_standby_names='ANY 1(og-node2)'"
gs_guc set -N all -I all -c "synchronous_commit=on"
# 两备中任一同步(一主两备,容忍一个备机故障)
gs_guc set -N all -I all -c "synchronous_standby_names='ANY 1(og-node2,og-node3)'"
# 全同步(两备都确认,性能最差)
gs_guc set -N all -I all -c "synchronous_standby_names='FIRST 2(og-node2,og-node3)'"
gs_om -t restart
| 配置 | RPO | 写入延迟 | 可用性 |
|---|---|---|---|
synchronous_commit=off |
可能丢秒级 | 最低 | 最高 |
ANY 1(...) |
0(至少一个备机确认) | 中 | 高 |
FIRST 2(...) |
0 | 最高 | 低(备机全挂则主库不可写) |
12.5 CM(Cluster Manager)
CM 是 openGauss 3.0 引入的高可用组件,负责自动故障检测与切换,替代早期的 gs_om 手工切换。
# 查看 CM 状态
cm_ctl query -Cv
# 输出关键字段
# cluster_state Normal / Degraded
# node_state Primary / Standby / Down
# cm_state Normal / Down
# 启动/停止
cm_ctl start
cm_ctl stop
# 单节点
cm_ctl start -n 1 -D /usr/local/opengauss/data
# 查看 CM 日志
tail -f /var/log/omm/cm/cm_agent/cm_agent.log
tail -f /var/log/omm/cm/cm_server/cm_server.log
| CM 进程 | 作用 |
|---|---|
cm_agent |
每节点一个,监控本机实例,上报状态 |
cm_server |
集群级,仲裁与决策(必须奇数个) |
cm_ctl |
客户端命令行 |
CM 与 gs_om 不要混用。装了 CM 后用
cm_ctl,gs_om -t start/stop会被 CM 干扰(停了又自动拉起)。只有 CM 挂了才临时用gs_ctl手工操作,修好 CM 后要gs_om -t refreshconf同步状态。
13. 日志体系
13.1 日志类型
| 日志 | 路径 | 内容 |
|---|---|---|
| 运行日志 | /var/log/omm/pg_log/ 或 $PGDATA/pg_log/ |
启动、错误、慢 SQL |
| WAL | $PGDATA/pg_xlog/ |
事务日志 |
| CM 日志 | /var/log/omm/cm/ |
集群管理 |
| 审计日志 | $GAUSSHOME/bin/ 或独立目录 |
需开启审计 |
| OM 日志 | /var/log/omm/omm/ |
安装、启停操作 |
| core dump | corePath 指定目录 |
崩溃分析 |
# 实时跟踪
tail -f /var/log/omm/pg_log/postgresql-*.log
# 找错误
grep -E 'ERROR|FATAL|PANIC' postgresql-*.log | tail -100
# 按时间段
awk '/2026-11-05 09:2[0-9]/,/2026-11-05 09:3[0-9]/' postgresql-*.log
# 统计错误类型
grep -oE 'ERROR:.*' postgresql-*.log | sort | uniq -c | sort -rn | head -20
13.2 日志参数
gs_guc reload -N all -I all -c "log_min_duration_statement=1000" # 慢 SQL 1s
gs_guc reload -N all -I all -c "log_statement='ddl'" # 记录 DDL
gs_guc reload -N all -I all -c "log_checkpoints=on"
gs_guc reload -N all -I all -c "log_connections=on"
gs_guc reload -N all -I all -c "log_disconnections=on"
gs_guc reload -N all -I all -c "log_line_prefix='%m %u %d %p %r '" # 时间/用户/库/pid/客户端
gs_guc reload -N all -I all -c "log_rotation_age=1d"
gs_guc reload -N all -I all -c "log_rotation_size=100MB"
13.3 审计
-- 查看审计开关
SHOW audit_enabled;
SHOW audit_directory;
-- 开启审计(需重启)
gs_guc set -N all -I all -c "audit_enabled=on"
-- 审计用户操作
CREATE AUDIT POLICY audit_ddl
ACCESS CREATE, ALTER, DROP;
AUDIT POLICY audit_ddl TO app;
-- 查看审计日志(需审计管理员权限)
SELECT * FROM pg_query_audit('2026-11-05 00:00:00', '2026-11-05 23:59:59')
WHERE type = 'ddl' LIMIT 50;
-- 审计策略
SELECT * FROM pg_audit_policy;
14. 性能诊断
14.1 执行计划
-- 基本计划
EXPLAIN SELECT * FROM orders WHERE user_id = 1001;
-- 实际执行(含耗时、行数、内存)
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT * FROM orders WHERE user_id = 1001;
-- 只看代价
EXPLAIN (COSTS true) SELECT ...;
执行计划危险信号:
| 现象 | 含义 | 处置 |
|---|---|---|
Seq Scan + 大表 |
全表扫描 | 补索引 |
rows= 估算与实际差 10 倍 |
统计信息过期 | ANALYZE |
Nested Loop 且外层行数大 |
JOIN 方式选错 | 收集统计信息 / 改写 |
Sort Method: external merge |
排序落盘 | 调大 work_mem |
Buffers: shared read= 很大 |
缓存命中率低 | 调大 shared_buffers |
HashAggregate 溢出 |
哈希表过大 | 调大 work_mem |
14.2 dbe_perf 性能视图
openGauss 用 dbe_perf schema 替代 PG 的 pg_stat_statements:
-- TOP SQL(按总耗时)
SELECT * FROM dbe_perf.statement
ORDER BY total_elapse_time DESC LIMIT 20;
-- 关键字段
SELECT unique_query_id, substr(query,1,80) sql,
n_calls, total_elapse_time/1000 total_ms,
(total_elapse_time/n_calls)/1000 avg_ms,
n_returned_rows, n_tuples_fetched,
n_blocks_fetched, n_blocks_hit
FROM dbe_perf.statement
ORDER BY total_elapse_time DESC LIMIT 20;
-- 历史语句(按时间段)
SELECT * FROM dbe_perf.statement_history
WHERE start_time > now() - interval '1 hour'
ORDER BY db_time DESC LIMIT 20;
-- 等待事件
SELECT * FROM dbe_perf.wait_events ORDER BY counts DESC LIMIT 20;
-- 当前活跃会话(ASP)
SELECT * FROM dbe_perf.local_active_session
WHERE sample_time > now() - interval '10 minutes';
-- 实例级统计
SELECT * FROM dbe_perf.global_instance_time;
| 视图 | 用途 |
|---|---|
dbe_perf.statement |
归一化 SQL 统计(类似 pg_stat_statements) |
dbe_perf.statement_history |
历史 SQL,含执行计划 |
dbe_perf.wait_events |
等待事件汇总 |
dbe_perf.local_active_session |
采样活跃会话(ASP) |
dbe_perf.os_runtime |
OS 指标 |
dbe_perf.memory_node_detail |
内存节点详情 |
14.3 WDR 报告
WDR(Workload Diagnosis Report)是 openGauss 的性能快照对比工具,相当于 Oracle 的 AWR:
-- 1) 创建快照
SELECT create_wdr_snapshot();
-- 2) 查看快照
SELECT * FROM snapshot.snapshot ORDER BY start_ts DESC LIMIT 10;
-- 3) 生成报告(两个快照 ID)
SELECT generate_wdr_report(1, 2, 'all', 'node1', 'node2');
-- 4) 报告会写到 $GAUSSHOME/bin 或指定目录
# 也可以用 gs_wdr 工具(部分版本)
gs_wdr_report --begin-snap-id 1 --end-snap-id 2 --report-type all
WDR 的前提:
enable_wdr_snapshot=on,且已有至少两个快照。默认每小时自动生成一个快照,保留 8 天。
14.4 锁与阻塞
-- 当前锁等待
SELECT
w.pid AS waiting_pid,
w.usename AS waiting_user,
w.query AS waiting_query,
b.pid AS blocking_pid,
b.usename AS blocking_user,
b.query AS blocking_query
FROM pg_stat_activity w
JOIN pg_locks l1 ON w.pid = l1.pid AND NOT l1.granted
JOIN pg_locks l2 ON l1.locktype = l2.locktype
AND l1.database IS NOT DISTINCT FROM l2.database
AND l1.relation IS NOT DISTINCT FROM l2.relation
AND l2.granted
JOIN pg_stat_activity b ON b.pid = l2.pid;
-- 锁明细
SELECT * FROM pg_locks WHERE NOT granted;
-- 长事务
SELECT pid, usename, state, now() - xact_start AS xact_age, query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY xact_age DESC LIMIT 10;
-- 杀会话
SELECT pg_terminate_backend(pid);
14.5 内存诊断
-- 各模块内存(openGauss 特有)
SELECT * FROM pv_session_memory_detail ORDER BY usedsize DESC LIMIT 20;
SELECT * FROM pv_total_memory_detail;
-- 会话级内存
SELECT * FROM pv_session_memory ORDER BY usedsize DESC LIMIT 20;
-- 共享内存
SELECT * FROM pg_shared_memory_detail ORDER BY size DESC LIMIT 20;
# OS 层面
free -g
ps -eLf | grep gaussdb | wc -l # 线程数
top -H -p $(pgrep -f gaussdb | head -1) # 线程级 CPU
15. 空间、VACUUM 与膨胀
15.1 空间统计
-- 库级
SELECT datname, pg_size_pretty(pg_database_size(datname)) size
FROM pg_database ORDER BY pg_database_size(datname) DESC;
-- 表级 Top20
SELECT schemaname, relname,
pg_size_pretty(pg_total_relation_size(relid)) total,
pg_size_pretty(pg_relation_size(relid)) table_size,
pg_size_pretty(pg_indexes_size(relid)) index_size
FROM pg_stat_user_tables
ORDER BY pg_total_relation_size(relid) DESC LIMIT 20;
-- 单表详细
SELECT pg_size_pretty(pg_total_relation_size('orders')) AS total,
pg_size_pretty(pg_relation_size('orders')) AS heap,
pg_size_pretty(pg_indexes_size('orders')) AS indexes;
15.2 VACUUM
-- 普通 VACUUM(不锁表,回收空间给后续复用)
VACUUM orders;
VACUUM VERBOSE orders;
-- VACUUM FULL(锁表,真正还给操作系统)
VACUUM FULL orders;
-- 并行 VACUUM
SET query_dop = 4;
VACUUM FULL orders;
-- 分析统计信息
ANALYZE orders;
ANALYZE VERBOSE;
-- 查看死元组比例
SELECT relname, n_live_tup, n_dead_tup,
ROUND(n_dead_tup::numeric / GREATEST(n_live_tup,1) * 100, 2) dead_pct,
last_vacuum, last_autovacuum
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC;
| 操作 | 锁 | 空间回收 | 适用 |
|---|---|---|---|
VACUUM |
无(4 级) | 标记可复用,不还给 OS | 日常 |
VACUUM FULL |
排他(8 级) | 真正还给 OS | 严重膨胀 |
VACUUM ANALYZE |
无 | 同时更新统计 | 日常推荐 |
UStore 表不需要
VACUUM FULL(原地更新,无版本膨胀),只有 AStore 表需要。对 UStore 表执行VACUUM FULL会重建整表,纯属浪费。
15.3 膨胀排查
-- 估算膨胀率(需安装 pgstattuple 扩展或使用 openGauss 内置函数)
SELECT * FROM pg_stat_all_tables WHERE relname = 'orders';
-- 精确统计(openGauss 的 pgstattuple)
CREATE EXTENSION IF NOT EXISTS pgstattuple;
SELECT * FROM pgstattuple('orders');
-- 关注 dead_tuple_percent 与 free_percent
-- 表膨胀 Top10(用统计信息估算)
SELECT schemaname, relname, n_live_tup, n_dead_tup,
pg_size_pretty(pg_total_relation_size(relid)) size,
ROUND(n_dead_tup::numeric / GREATEST(n_live_tup + n_dead_tup,1) * 100, 1) dead_pct
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY pg_total_relation_size(relid) DESC LIMIT 10;
15.4 WAL 空间
-- WAL 目录大小
SELECT pg_size_pretty(SUM(size)) FROM pg_ls_dir('pg_xlog') AS f, pg_stat_file('pg_xlog/'||f) AS s;
-- 复制槽持有的 WAL(常见堆积原因)
SELECT slot_name, plugin, active,
pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn)) AS retained
FROM pg_replication_slots;
-- 删除废弃复制槽
SELECT pg_drop_replication_slot('slot_name');
WAL 暴涨三大原因:① 归档失败(
archive_command卡住);② 复制槽无人消费(逻辑复制断开);③ 备机长时间失联。三者都会让pg_xlog无限增长直到磁盘满。
16. 扩缩容、升级与迁移
16.1 扩容(加备机)
# 1) 新节点做预安装(root)
./gs_preinstall -U omm -G dbgrp -X cluster_config.xml
# 2) 扩容(omm)
gs_expansion -U omm -G dbgrp -X cluster_config.xml -h og-node3
# 3) 验证
gs_om -t status --detail
16.2 缩容(减备机)
# 1) 确认要删的节点是备机
gs_om -t status --detail
# 2) 删除
gs_dropnode -U omm -G dbgrp -h og-node3
# 3) 验证
gs_om -t status --detail
只能删备机。删主机前必须先
switchover把主角色移走。
16.3 升级
# 1) 停止业务,做全量备份
gs_probackup backup -B /backup/probackup --instance=og1 -b full
# 2) 解压新版本
tar xzf openGauss-7.0.0-*-all.tar.gz
# 3) 升级(omm)
gs_upgradectl -t upgrade --new-package /opt/software/openGauss_New
# 4) 查看升级状态
gs_upgradectl -t show
# 5) 提交(确认无误后,不可回滚)
gs_upgradectl -t commit
# 6) 回滚(提交前可用)
gs_upgradectl -t rollback
| 阶段 | 说明 |
|---|---|
upgrade |
替换二进制,旧版本保留在 $GAUSHHOME/../upgrade |
commit |
删除旧版本,不可逆 |
rollback |
回退到旧二进制(仅在 commit 前) |
升级窗口内不要执行 DDL。升级过程中元数据格式可能变化,DDL 会导致回滚失败。
16.4 从 PostgreSQL 迁移
| 差异点 | PG | openGauss | 迁移处置 |
|---|---|---|---|
| 工具名 | psql/pg_dump |
gsql/gs_dump |
换工具 |
| 端口 | 5432 | 15400 | 改连接串 |
| WAL 命名 | pg_wal(10+) |
pg_xlog |
改脚本 |
| 复制槽 | 支持 | 支持(部分版本) | 核对版本 |
| 扩展 | pg_stat_statements |
dbe_perf.statement |
改监控 SQL |
| 存储引擎 | 仅 heap | AStore/UStore/列存 | 按场景选 |
| 兼容模式 | 无 | DBCOMPATIBILITY |
建库时定 |
# 迁移步骤(小库)
# 源库(PG)
pg_dump -h pg-host -U postgres -Fc app_db > app_db.dmp
# 目标库(openGauss)
createdb -p 15400 app_db
gs_restore -p 15400 -d app_db app_db.dmp
直接用
pg_dump的备份给gs_restore大部分情况可用,但涉及扩展、GENERATED列、IDENTITY列时可能失败。生产迁移建议用华为的 gs_migration 或第三方的 MTK(Migration Toolkit)。
17. 高频故障速查
17.1 起不来
| 现象 | 排查 |
|---|---|
could not create shared memory |
① kernel.shmmax/shmall 太小 → ② shared_buffers/max_process_memory 超物理内存 |
could not bind |
端口被占 → ss -lntp | grep 15400 |
permission denied |
数据目录属主不是 omm → chown -R omm:dbgrp $PGDATA |
database system was not properly shut down |
上次是 kill -9,正在崩溃恢复,等它跑完 |
FATAL: the database system is starting up |
恢复中,看日志进度 |
no space left on device |
磁盘满,清 WAL 或归档 |
# 启动失败第一时间看这三处
tail -200 /var/log/omm/pg_log/postgresql-*.log
ls -ld $PGDATA
df -h
17.2 连不上
| 现象 | 处置 |
|---|---|
Connection refused |
gs_ctl status -D $PGDATA → 进程是否在 → 端口 → 防火墙 |
no pg_hba.conf entry |
加 pg_hba.conf 一行,gs_ctl reload |
password authentication failed |
① 密码错 → ② password_encryption_type 变了 → ③ 用户被锁 |
too many clients already |
调大 max_connections,或检查连接池泄漏 |
remaining connection slots are reserved |
保留连接被占,用 sysadmin 登录杀会话 |
-- 保留连接(openGauss 特有,给管理员留的)
SHOW reserved_connections;
-- 管理员用户可占用保留连接
17.3 主备不同步
# 看状态
gs_ctl query -D $PGDATA
# 判断
# db_state = Need repair → 必须 build
# 位点差距持续增大 → 查网络/IO
# 备机 CPU 100% → 回放跟不上,看 recovery_time_target
| 原因 | 判断 | 处置 |
|---|---|---|
| 网络抖动 | ping/丢包率 | 修网络,短暂延迟会自愈 |
| 备机 IO 慢 | iostat -x 1 看 %util |
换盘 |
| 主库大事务 | pg_stat_activity 有长事务 |
拆批 |
| 备机回放慢 | recovery_time_target 太小 |
调大或设 0(不限速) |
| WAL 被删 | 备机报 requested WAL segment has already been removed |
必须全量 build |
17.4 磁盘满
# 1) 找占用
du -sh $PGDATA/* | sort -rh | head -10
du -sh /var/log/omm/* | sort -rh | head -10
# 2) 常见大头
# pg_xlog WAL 堆积(归档失败/复制槽)
# base 数据文件
# pg_log 日志未轮转
# corefile 崩溃转储
# 3) 应急清理(按安全性排序)
find /var/log/omm/pg_log -name "*.log" -mtime +7 -delete # 安全
rm -f /archive/og/0000000100000000000000* # 危险,先确认已备份
绝对不要直接删
pg_xlog里的文件。删了会导致崩溃恢复失败、备机要求全量重建。正确做法是修归档、删复制槽、或调max_wal_size。
17.5 OOM
-- openGauss 的 OOM 多半是 max_process_memory 超限
SHOW max_process_memory;
SHOW shared_buffers;
SHOW max_connections;
SHOW work_mem;
-- 内存分布
SELECT * FROM pv_total_memory_detail;
SELECT * FROM pv_session_memory_detail ORDER BY usedsize DESC LIMIT 10;
# OS 层 OOM 记录
dmesg -T | grep -i "out of memory"
grep -i "oom" /var/log/messages
| 原因 | 处置 |
|---|---|
max_process_memory 太小 |
调到物理内存 60~70% |
| 连接数 × work_mem 超限 | 降 max_connections 或 work_mem,开线程池 |
| 大查询排序/哈希 | 限 statement_timeout,优化 SQL |
| 列存缓冲过大 | 降 cstore_buffers |
18. 危险命令与避坑清单
| # | 命令 | 风险 | 防护 |
|---|---|---|---|
| 1 | rm -rf $PGDATA |
数据全丢 | 先 gs_basebackup 或 gs_probackup |
| 2 | kill -9 gaussdb |
崩溃恢复,可能几十分钟 | 用 gs_ctl stop -m fast |
| 3 | gs_uninstall --delete-data |
删集群+数据 | 确认集群名,生产禁用 |
| 4 | 直接删 pg_xlog 文件 |
备机全量重建、PITR 断档 | 修归档 / 删复制槽 |
| 5 | VACUUM FULL 大表 |
排他锁,业务全停 | 用 pg_repack 或低峰执行 |
| 6 | DROP DATABASE |
不可恢复 | 先 gs_dump;限制权限 |
| 7 | UPDATE/DELETE 无 WHERE |
全表修改 | 事务内先 SELECT COUNT(*);\set ON_ERROR_STOP on |
| 8 | gs_guc set 改 max_process_memory 调小 |
实例起不来 | 算好余量,改前备份 postgresql.conf |
| 9 | CM 模式下 gs_om -t stop |
停了又被拉起,状态不一致 | 用 cm_ctl stop |
| 10 | failover 代替 switchover |
丢 WAL,原主需重建 | 能用 switchover 就别 failover |
变更前五步
- 备份:
gs_probackup backup -b full,记录 backup-id; - 确认角色:
gs_om -t status --detail,别在备机上做写操作; - 确认 CM 状态:
cm_ctl query -Cv,CM 异常时先修 CM; - 备份配置:
cp postgresql.conf postgresql.conf.bak.$(date +%F); - 留痕:记录变更前后
pg_stat_replication与pg_stat_activity快照。
19. 附录:一键巡检脚本
#!/usr/bin/env bash
# og_health_check.sh —— 一分钟巡检
# 用法:su - omm 后执行 ./og_health_check.sh
set -uo pipefail
export GAUSSHOME=${GAUSSHOME:-/usr/local/opengauss}
export PGDATA=${PGDATA:-/usr/local/opengauss/data}
PORT=${PORT:-15400}
Q() { gsql -d postgres -p "$PORT" -A -F $'\t' -t -c "$1" 2>/dev/null; }
echo "==================== openGauss 巡检 $(date '+%F %T') ===================="
echo -e "\n--- 1. 版本 ---"
Q "SELECT version();"
echo -e "\n--- 2. 集群状态 ---"
gs_om -t status --detail 2>/dev/null | sed -n '1,25p'
echo -e "\n--- 3. 实例角色与复制延迟 ---"
Q "SELECT client_addr, state, sync_state,
pg_xlog_location_diff(pg_current_xlog_location(), replay_location) AS lag_bytes
FROM pg_stat_replication;"
echo -e "\n--- 4. 连接数 ---"
Q "SELECT 'total=' || COUNT(*) FROM pg_stat_activity;
SELECT 'active=' || COUNT(*) FROM pg_stat_activity WHERE state = 'active';"
echo -e "\n--- 5. 长事务(>5min)---"
Q "SELECT pid, usename, ROUND(EXTRACT(EPOCH FROM (now()-xact_start))) AS sec,
LEFT(query,80)
FROM pg_stat_activity
WHERE xact_start IS NOT NULL AND now()-xact_start > interval '5 min'
ORDER BY sec DESC LIMIT 10;"
echo -e "\n--- 6. 慢 SQL TOP5 ---"
Q "SELECT ROUND(total_elapse_time/1000,2) AS total_ms,
n_calls, LEFT(query,80)
FROM dbe_perf.statement
ORDER BY total_elapse_time DESC LIMIT 5;"
echo -e "\n--- 7. 死元组比例(>20% 关注)---"
Q "SELECT relname, n_live_tup, n_dead_tup,
ROUND(n_dead_tup::numeric/GREATEST(n_live_tup,1)*100,1) AS dead_pct
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000 ORDER BY dead_pct DESC LIMIT 10;"
echo -e "\n--- 8. 归档状态 ---"
Q "SELECT archived_count, failed_count, last_archived_wal, last_failed_wal
FROM pg_stat_archiver;"
echo -e "\n--- 9. 复制槽持有 WAL ---"
Q "SELECT slot_name, active,
pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn)) AS retained
FROM pg_replication_slots;"
echo -e "\n--- 10. 磁盘水位 ---"
df -h "$PGDATA" /archive 2>/dev/null | awk 'NR==1 || /[0-9]%/{print " "$0}'
echo -e "\n--- 11. WAL 目录大小 ---"
du -sh "$PGDATA/pg_xlog" 2>/dev/null | awk '{print " "$0}'
echo -e "\n--- 12. 日志 ERROR 计数(近 500 行)---"
for f in /var/log/omm/pg_log/postgresql-*.log; do
[ -f "$f" ] && printf " %-60s %s\n" "$f" "$(tail -500 "$f" | grep -c 'ERROR')"
done
echo -e "\n==================== 巡检结束 ===================="
速查表
| 需求 | 命令 |
|---|---|
| 集群状态 | gs_om -t status --detail |
| CM 状态 | cm_ctl query -Cv |
| 单实例状态 | gs_ctl query -D $PGDATA |
| 启停 | gs_om -t start/stop 或 cm_ctl start/stop |
| 切主 | gs_om -t switch --instance <node> |
| 备机重建 | gs_ctl build -D $PGDATA -b full |
| 改参数 | gs_guc reload -N all -I all -c "k=v" |
| 逻辑备份 | gs_dump -Fc -f out.dmp db |
| 物理备份 | gs_probackup backup -b full |
| 慢 SQL | dbe_perf.statement |
| WDR | generate_wdr_report(1,2,'all') |
| 扩容 | gs_expansion -h <new-node> |
| 升级 | gs_upgradectl -t upgrade |
最后一句:openGauss 的坑集中在三处——端口不是 5432、WAL 还叫
pg_xlog、gs_om/cm_ctl/gs_ctl三层别混用。把这三条记住,剩下的都是标准关系库运维。