数据库教程FGMT81:国产数据库-华为高斯GaussDB数据库培训(openGauss)
数据库教程FGMT81:国产数据库-华为高斯GaussDB数据库培训(openGauss)
## 一、前言与本套风哥教程大纲介绍
在信创替代全面推进的背景下,金融、政务、运营商、能源、交通等关键行业的核心系统正在加速从国外商业数据库向国产数据库迁移。华为高斯体系包含三条产品线:面向私有化部署的开源内核 openGauss、面向公有云与私有云托管的 GaussDB 企业版管理平台 TPOPS、面向 PB 级数据仓库的 GaussDB(DWS)。本套风哥教程聚焦开源内核 openGauss,它是华为 2019 年开源、基于 PostgreSQL 内核深度增强的关系型数据库,支持 x86 与鲲鹏 ARM 双架构,具备高可用、高安全、高并发与事务强一致能力,是国产替代项目中落地最广的内核之一。
风哥教程本文面向已经具备 Linux 基础与关系型数据库通用概念的运维工程师、DBA 与开发人员,目标是让学习者在一套两台物理机(或虚拟机)环境中,完整走完 openGauss 的单机安装、参数规划、用户权限管理、逻辑与物理备份恢复、一主一备流复制搭建、主备切换、安全加固、监控与性能优化的全流程。本套风哥教程所有配置参数均按 64GB 内存、8 颗 CPU 的生产规格给出,所有命令均可在 RHEL/CentOS/openEuler/麒麟 Linux 上直接套用,所有路径统一规划为 /fgedudb,数据库名与实例名统一为 fgedudb,业务用户名统一为 fgedu,避免学习者在实验中被命名差异干扰。
本套风哥教程的实验环境规划如下:主节点 fgedu-net-cn1(IP 地址 192.168.10.11),备节点 fgedu-net-cn2(IP 地址 192.168.10.12),两台机器均为 64GB 内存、8 vCPU,操作系统为 Linux 内核 4.18 以上(RHEL 9.3 / openEuler 22.03 / 麒麟 V10 均可),软件版本统一为 openGauss 5.0.5 LTS x86_64。主节点承担初始化、备份、主备搭建等全部实操,备节点用于流复制与切换演练。
本套风哥教程的内容结构分为四个部分:第一部分即前言与大纲介绍;第二部分为理论篇,讲解 openGauss 的起源与版本体系、进程与内存体系结构、事务与 MVCC、流复制高可用原理、备份恢复原理、安全体系与性能基础;第三部分为实战篇,按操作系统准备、单机安装初始化、基础管理、逻辑备份恢复、物理备份与时间点恢复、一主一备流复制与切换、安全加固、监控优化、故障诊断九个实验逐项给出步骤与命令;第四部分为风哥针对本文总结。学习时建议先通读理论篇建立心智模型,再对照实战篇逐条敲命令,理论与命令的比例约为三成与六成,其余一成用于承上启下,结尾为风哥针对本文总结。
本套风哥教程涉及的核心术语中英文对照先在此统一列出,后文不再重复解释:WAL(Write-Ahead Logging,预写日志)、MVCC(Multi-Version Concurrency Control,多版本并发控制)、PITR(Point-In-Time Recovery,时间点恢复)、LSN(Log Sequence Number,日志序列号)、CM(Cluster Manager,集群管理器)、DMS(Distributed Memory Service,分布式内存服务)、DSS(Distributed Storage Service,分布式存储服务)、GUC(Grand Unified Configuration,数据库统一配置参数)、SGA(s-hared Memory,共享内存区)、bgwriter(后台写盘进程)、checkpoint(检查点)、vacuum(垃圾回收)。
## 二、理论篇
### 2.1 openGauss 的起源、版本体系与产品边界
openGauss 是华为 2019 年 6 月在开发者大会上开源的关系型数据库内核,其技术血缘来自 PostgreSQL,华为在其之上做了大量内核级增强:自研的多核 NUMA 感知优化、无锁化线程池、行列共存存储、安全认证与审计增强、资源池化与一写多读架构等。理解 openGauss 与商业产品的边界是学习的第一步:openGauss 是开源内核,社区版本可免费使用,主备流复制、物理备份、审计等能力均在内核中;GaussDB 企业版(TPOPS 形态)是华为基于同一内核封装的商业托管产品,增加了可视化管理平台、自动运维、弹性扩缩容等云服务能力;GaussDB(DWS) 是 MPP 分布式数据仓库,面向分析型负载,与本套风哥教程的事务型内核不是同一套部署形态。
版本选择上,生产环境建议选用 LTS 长期支持版本,本套风哥教程采用 5.0.5。版本演进上,1.0 系列完成开源奠基,2.x/3.x 完善主备与备份工具链,5.x 引入资源池化、oGRAC 多写、向量引擎等特性,6.x/7.x 进一步强化云原生与 AI 能力。学习者需要知道:openGauss 的大版本号必须在主备两端、备份与恢复两端保持一致,跨大版本只能通过逻辑迁移或升级工具完成,不能直接用物理备份还原。
与 PostgreSQL 的差异也要心中有数:openGauss 默认采用线程模型而非每会话一进程,管理工具统一以 gs_ 前缀命名(gs_ctl、gs_initdb、gs_dump、gs_probackup、gs_guc、gs_checkperf),认证默认使用 s-ha256 与 md5 双模式,配置文件仍为 postgresql.conf 与 pg_hba.conf,SQL 语法高度兼容 PostgreSQL,这使得有 PostgreSQL 经验的 DBA 迁移成本很低。
### 2.2 进程体系与内存结构
openGauss 实例由一个 gaussdb 主进程与若干后台线程组成。主节点上的关键后台线程包括:walwriter 负责把事务提交产生的 WAL 记录从内存缓冲区刷写到日志文件;bgwriter 负责把共享缓冲区中的脏页异步批量写回数据文件,避免 checkpoint 瞬间 IO 尖峰;checkpointer 周期性触发检查点,把已提交事务对应的脏页与 WAL 落盘并推进检查点位置;walwriter 之外还有 walsender 线程,主节点通过它把 WAL 日志流推送给备节点;备节点对应运行 walreceiver 线程接收日志并回放;autovacuum launcher 负责调度各库的 autovacuum worker 清理死元组;统计收集线程维护 pg_stat_* 统计视图。此外还有死锁检测线程、页回放线程、线程池管理线程等。
内存结构分为共享内存与本地内存两部分。共享内存中的核心区域是数据缓冲区(由 s-hared_buffers 控制),缓存表与索引的数据页;WAL 缓冲区(wal_buffers)暂存待落盘的日志记录;还有锁表、会话哈希、事务状态数组等。本地内存是每个会话私有、按需分配的工作区,work_mem 控制排序与哈希连接可用的内存,maintenance_work_mem 控制建索引、vacuum 等维护操作可用的内存。按 64GB 内存规划时,s-hared_buffers 取物理内存的四分之一即 16GB,effective_cache_size 取四分之三即 48GB 作为操作系统页缓存的预估,work_mem 取 64MB,maintenance_work_mem 取 2GB,这一组比例是 OLTP 场景的稳妥基线。
存储结构上,一个 openGauss 实例下可以创建多个数据库(本套风哥教程使用 fgedudb),数据库内按模式(schema)组织表、视图、函数等对象,表空间(tablespace)映射到文件系统目录。数据以堆表形式存储,每一行元组带系统列 xmin/xmax 与版本指针,配合 WAL 实现崩溃恢复;索引支持 B 树、哈希、GIN、GiST、BRIN,列存表面向大宽表分析场景。WAL 日志是高可用与恢复的基石:任何修改先写日志再改数据页,日志按段文件(segment)滚动,检查点推进后旧日志段才可被回收或归档。
openGauss 默认采用线程池模型替代 PostgreSQL 的每会话一进程:所有会话复用一组常驻工作线程,避免高并发下进程创建与上下文切换的开销,线程池大小由 thread_pool_group_num 与 thread_pool_size 控制。在 NUMA 多路服务器上,数据库可通过 numactl 绑定节点,让内存访问尽量本地命中,减少跨节点访存延迟;本套风哥教程的 8 CPU 单路实验不强制绑定,但学习者在多路生产机上应理解 NUMA 亲和性对尾延迟的影响。共享缓冲区采用时钟扫描(clock-sweep)算法淘汰脏页,bgwriter 与 checkpointer 分工:前者持续小批量写盘平滑 IO,后者周期性整体推进检查点,二者参数配合决定了突发写入时的 IO 峰值形态。
### 2.3 事务、MVCC 与并发控制
openGauss 实现了完整的 ACID 事务与 MVCC 多版本并发控制。读操作不阻塞写、写操作不阻塞读的原理是:每行保存多个版本,读会话按事务开始时的快照(snaps-hot)挑选可见版本,旧版本由 vacuum 回收。隔离级别支持读已提交(read committed,默认)、可重复读(repeatable read)与串行化。锁的层次分为表级锁(ACCESS s-hARE、ROW s-hARE、ROW EXCLUSIVE、s-hARE、s-hARE ROW EXCLUSIVE、EXCLUSIVE 等)与行级锁(行锁仅锁元组版本,不锁物理行位置),此外还有咨询锁(advisory lock)供应用层自定义协调。
需要重点理解的是死元组与膨胀:UPDATE/DELETE 并不物理删除旧行,而是标记为死元组,vacuum 扫描并回收可复用空间,autovacuum 自动触发但受统计信息阈值控制。长期不 vacuum 会导致表与索引膨胀、查询变慢、事务 ID 回绕(wraparound)强制停机。运维中要养成定期查看 pg_stat_user_tables 的 n_dead_tup、last_autovacuum 的习惯。
隔离级别上,读已提交(read committed)每条语句都取一次新快照,语句之间能看到其他事务的新提交;可重复读(repeatable read)整个事务共用一个快照,事务内多次读取结果一致,但无法看到事务开始后的新提交;串行化通过谓词锁检测写偏序冲突,冲突时回滚其中一方。MVCC 的代价是旧版本长期堆积,因此快照不能无限老:长事务即使只执行 SELECT,也会阻止 vacuum 回收它仍能看到的死元组,这是生产库”明明没写数据却越来越大”的常见原因,对应实战八中的 idle_in_transaction_session_timeout 治理。锁的兼容性矩阵要记住:读不阻塞写、写不阻塞读,但写与写在同一行上排队,DDL(如 ALTER TABLE)会持有 ACCESS EXCLUSIVE 表锁,阻塞所有访问,必须放在低峰执行。
### 2.4 流复制高可用原理
openGauss 的一主一备(或一主多备)基于物理流复制:主节点产生的 WAL 日志通过 walsender 实时推送到备节点的 walreceiver,备节点在回放日志的同时保持只读对外服务。复制模式分异步与同步:异步模式下主节点提交无需等待备节点确认,性能高但主节点宕机可能丢失少量已提交事务;同步模式下主节点提交需等待至少一个备节点写入 WAL 并返回确认,数据零丢失但写延迟略增,由 synchronous_standby_names 指定参与同步的备节点名单。
复制槽(replication slot)是保证 WAL 不被误删的机制:主节点为每个备节点保留一个槽,槽记录备节点已回放的位置,未被槽消费的 WAL 段不会被回收,代价是备节点长期断连会造成主节点磁盘膨胀,需要定期监控槽的延迟。主备切换有两种路径:计划内维护使用 switchover 优雅切换,主节点降级为备、指定备节点提升为主;故障场景下主节点失联,人工或 CM 组件执行 promote 把备节点提升为主,原主恢复后必须以新备节点身份重新 build 加入集群,不能直接旧主回切。
脑裂是高可用设计必须规避的风险:当网络分区导致主节点与备节点失联,而外部仲裁仍认为原主存活时,可能出现两个主同时接受写,造成数据分叉。一主一备的人工切换流程要求在 promote 前确认原主确实不可写,恢复旧主时必须重新拉取新主备份而非直接启动旧数据目录,正是为了从流程上杜绝双主。引入 CM 自动仲裁时,仲裁多数派(多数节点存活)才允许提升,单节点分区不会触发切换。同步复制在故障切换时的取舍是:同步模式下若同步备失联,主节点提交会被阻塞,需要预先配置备库兜底或临时降级为异步,这是预案设计的一部分。
### 2.5 备份与恢复原理
备份分逻辑备份与物理备份两条路线。逻辑备份工具为 gs_dump(单库)与 gs_dumpall(全库含角色与表空间定义),导出为 SQL 文本或自定义压缩格式,适合跨版本迁移与小批量数据导出,恢复用 gsql 执行 SQL 或 gs_restore 导入自定义格式。物理备份工具为 gs_probackup,基于数据文件级别的全量(FULL)与 PTRACK 增量备份,配合 WAL 归档实现 PITR:先还原全量备份的数据目录,再通过 restore_command 重放归档 WAL 到指定时间点、事务 ID 或 LSN。生产环境的标准组合是:每日一次全量、每小时 PTRACK 增量、WAL 实时归档,恢复时按备份集加归档日志回退到故障前最近一致点。
两条路线的选型边界要分清:逻辑备份与数据库版本、字符集兼容范围宽,导出的是可阅读的 SQL,适合版本升级前的兜底与单表误删恢复,但数据量大时导出导入耗时长,且无法恢复到任意时间点;物理备份是文件级快照,恢复速度快、支持 PITR,但备份集只能在同版本、同架构上还原,且必须配合连续的 WAL 归档才能覆盖两次备份之间的变更。实际项目中两者并存:物理备份承担灾难恢复主线,逻辑备份承担迁移与精细恢复兜底,不能用一种替代另一种。PITR 的本质是”还原全量基线 + 重放 WAL 到目标点”,因此归档目录的连续性比备份集本身更关键,归档断档则断点之后不可恢复。
### 2.6 安全体系
openGauss 的安全模型以 pg_hba.conf 的认证规则为入口,按连接来源(本地套接字、TCP)、目标库、用户、来源网段、认证方法逐行匹配,认证方法包括 trust(免密,仅限本机)、md5、s-ha256、cert(证书)等。password_encryption_type 控制密码哈希算法。数据库内通过角色(role)与权限(GRANT/REVOKE)实现最小权限,支持模式级、表级、列级权限与行级安全策略。审计由 audit_enabled 开关控制,记录登录、权限变更、DDL 等操作到审计日志,等保场景下必须开启。生产环境还应配置 SSL 加密传输、密码复杂度策略、连接数限制与登录失败锁定。
### 2.7 性能优化基础
openGauss 的优化器基于代价(cost-based),EXPLAIN 展示执行计划,EXPLAIN ANALYZE 实际执行并输出每一步真实耗时。常见计划节点包括顺序扫描 Seq Scan、索引扫描 Index Scan、位图扫描 Bitmap Scan、嵌套循环 Nested Loop、哈希连接 Has-h Join、合并连接 Merge Join。优化的抓手包括:让统计信息保持新鲜(ANALYZE)、为高频过滤列建合适索引、避免 SELECT * 与隐式类型转换、控制 work_mem 让排序走内存而非落盘、用资源池(resource pool)限制大查询抢占资源。慢查询通过 log_min_duration_statement 记录,是优化的第一手线索。
代价估算的依据是统计信息中的行数、宽度、直方图与常见值列表:优化器假设谓词命中比例由统计信息推算,一旦统计信息过期,估算行数与真实行数偏差可达几个数量级,优化器就会选错连接方式与扫描方式,这是绝大多数”同样的 SQL 换个环境就变慢”的根因。因此 ANALYZE 不是一次性动作,而是随数据变化持续维护的例行工作。排序与聚合消耗的内存由 work_mem 决定,单个会话的每个排序节点独立申请一份 work_mem,并发量大时 work_mem 不是越大越好,过大反而会在并发下把内存打爆;maintenance_work_mem 只服务于建索引与 vacuum,与会话并发无关,可以给得相对宽裕。
### 2.8 资源池化与集群组件简述
单机之外,openGauss 的高可用与弹性形态依赖几个核心组件理解即可,本套风哥教程不展开部署:CM(Cluster Manager)是集群管理器,负责节点状态探测、故障判定与自动切换,对外提供 cm_ctl 命令完成集群启停、节点增删与切换;DMS(Distributed Memory Service)在资源池化架构中管理共享内存池与全局锁;DSS(Distributed Storage Service)提供共享存储层,多实例共享一份数据文件实现一写多读。本套风哥教程实战六采用的是最经典的一主一备物理流复制,不依赖 CM,切换由人工命令完成,学习者先掌握这条主线,再去理解 CM 自动仲裁时不会被概念淹没。
### 2.9 安装形态与工具链边界
openGauss 提供三种部署路径:OM 工具(openGauss-om)一键部署、gs_install 脚本部署、gs_initdb 手动初始化。OM 工具默认以 omm 用户运行并自动完成参数调优与集群编排,适合生产批量交付;手动初始化路线由学习者自己控制用户、目录与参数,适合教学与定制环境,本套风哥教程采用手动路线。所有运维命令统一带 gs_ 前缀:gs_ctl 负责实例启停、切换、日志查看;gs_initdb 负责初始化;gs_guc 负责参数与认证配置的 set、reload、check;gs_dump/gs_dumpall/gs_restore 负责逻辑备份;gs_probackup 负责物理备份;gsql 是命令行客户端;gs_checkperf 与 gs_collector 负责性能采集;gs_expansion 负责在线扩容备节点。学习者记住这个前缀家族,遇到陌生命令先查 –help 即可。
## 三、实战篇
### 实战一:两台节点操作系统环境准备(fgedu-net-cn1 与 fgedu-net-cn2)
本实验在两台节点上同步执行,除特别注明外命令在两台机器上都要运行。所有操作以 root 完成,数据库运行用户为 fgedu。
**步骤 1:配置主机名与 hosts 解析。**
在 fgedu-net-cn1 上执行:
“`bas-h
hostnamectl set-hostname fgedu-net-cn1
“`
在 fgedu-net-cn2 上执行:
“`bas-h
hostnamectl set-hostname fgedu-net-cn2
“`
两台机器的 /etc/hosts 都追加如下解析,保证主机名互通:
“`bas-h
cat >> /etc/hosts << ‘EOF’
192.168.10.11 fgedu-net-cn1
192.168.10.12 fgedu-net-cn2
EOF
“`
验证互通:
“`bas-h
ping -c 2 fgedu-net-cn1
ping -c 2 fgedu-net-cn2
“`
**步骤 2:关闭防火墙与 SELinux(实验环境;生产环境应改为放通端口而非全关)。**
“`bas-h
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i ‘s/^SELINUX=.*/SELINUX=disabled/’ /etc/selinux/config
“`
**步骤 3:配置时间同步。** 主备流复制对时间一致性敏感,两台机器必须同步到同一 NTP 源:
“`bas-h
dnf install -y chrony
systemctl enable –now chronyd
chronyc sources
“`
**步骤 4:创建数据库用户与目录。** openGauss 手动安装不强制使用 omm 用户,本套风哥教程统一使用 fgedu:
“`bas-h
groupadd -g 1001 dba
useradd -u 1001 -g dba -m -s /bin/bas-h fgedu
echo ‘fgedu:Fgedu@2026’ | chpasswd
mkdir -p /fgedudb/app /fgedudb/data /fgedudb/backup /fgedudb/software
chown -R fgedu:dba /fgedudb
chmod -R 750 /fgedudb
“`
目录规划说明:/fgedudb/app 存放解压后的程序二进制,/fgedudb/data 存放数据目录,/fgedudb/backup 存放逻辑备份与 gs_probackup 备份集,/fgedudb/software 存放安装包。
**步骤 5:配置操作系统内核参数与资源限制。** 按 64GB 内存、8 CPU 规格,写入 /etc/sysctl.conf:
“`bas-h
cat >> /etc/sysctl.conf << ‘EOF’
# openGauss 64G/8C 内核参数
kernel.sem = 250 32000 100 1024
kernel.s-hmmax = 549755813888
kernel.s-hmall = 134217728
kernel.s-hmmni = 4096
kernel.sysrq = 0
net.core.somaxconn = 4096
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 40000 65535
vm.overcommit_memory = 1
vm.swappiness = 10
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
fs.file-max = 1000000
EOF
sysctl -p
“`
为 fgedu 用户配置资源限制,写入 /etc/security/limits.conf:
“`bas-h
cat >> /etc/security/limits.conf << ‘EOF’
fgedu soft nofile 65536
fgedu hard nofile 65536
fgedu soft nproc 65536
fgedu hard nproc 65536
fgedu soft stack unlimited
fgedu hard stack unlimited
fgedu soft core unlimited
fgedu hard core unlimited
EOF
“`
**步骤 6:安装依赖包。** RHEL/openEuler 执行:
“`bas-h
dnf install -y libaio libaio-devel flex bison ncurses-devel glibc-devel \
readline-devel zlib-devel openssl-devel pam-devel libxml2-devel \
libxslt-devel python3 perl-IPC-Cmd
“`
**步骤 7:配置 fgedu 用户免密 Ss-h(主备搭建时需要)。** 在 fgedu-net-cn1 上以 fgedu 用户执行:
“`bas-h
su – fgedu
ss-h-keygen -t rsa -P ” -f ~/.ss-h/id_rsa
ss-h-copy-id fgedu@fgedu-net-cn1
ss-h-copy-id fgedu@fgedu-net-cn2
exit
“`
在 fgedu-net-cn2 上同样生成密钥并互信:
风哥 itpux-com
“`bas-h
su – fgedu
ss-h-keygen -t rsa -P ” -f ~/.ss-h/id_rsa
ss-h-copy-id fgedu@fgedu-net-cn1
ss-h-copy-id fgedu@fgedu-net-cn2
exit
“`
验证免密:
“`bas-h
su – fgedu -c ‘ss-h fgedu-net-cn2 hostname’
“`
**步骤 8:关闭透明大页并规划磁盘挂载。** 透明大页(THP)会让数据库偶发延迟毛刺,两台机器都要关闭:
“`bas-h
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
cat >> /etc/rc.local << ‘EOF’
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
EOF
chmod +x /etc/rc.local
“`
数据盘挂载时建议加 noatime、nodiratime 选项,减少元组更新带来的额外写:
“`bas-h
mkdir -p /fgedudb
mount -o noatime,nodiratime,defaults /dev/vdb /fgedudb
blkid /dev/vdb
“`
将 UUID 写入 /etc/fstab 保证开机自动挂载:
“`bas-h
echo ‘UUID=<上一步得到的UUID> /fgedudb ext4 defaults,noatime,nodiratime 0 0’ >> /etc/fstab
“`
**步骤 9:检查资源限制与依赖版本。** 重新登录 fgedu 用户后验证 ulimit:
“`bas-h
su – fgedu -c ‘ulimit -n; ulimit -u’
“`
预期 nofile 为 65536。确认 gcc 与 Python 版本,openGauss 5.0.5 要求 Python3.6 以上:
“`bas-h
python3 –version
gcc –version | head -1
“`
**步骤 10:网络连通性与端口校验。** 两台机器互测 5432 端口与 Ss-h 端口,为后续安装与复制排除网络问题:
“`bas-h
ss-h fgedu-net-cn1 ‘ss -lnt | grep 22’
ss-h fgedu-net-cn2 ‘ss -lnt | grep 22’
ping -c 3 192.168.10.12
“`
若使用云平台或虚拟化环境,确认安全组放通 5432、22 端口,且两台机器在同一二层网络,避免跨路由带来的复制延迟。时间偏差超过几秒会导致备库回放异常,用 chronyc tracking 核对两台机器的偏移:
“`bas-h
chronyc tracking | grep -i ‘Last offset’
“`
### 实战二:openGauss 单机安装与初始化(fgedu-net-cn1)
**步骤 1:上传并解压安装包。** 将 openGauss-5.0.5-CentOS-64bit-all.tar.gz 上传到 /fgedudb/software,以 fgedu 用户解压:
“`bas-h
su – fgedu
cd /fgedudb/software
tar -zxf openGauss-5.0.5-CentOS-64bit-all.tar.gz -C /fgedudb/app
ls /fgedudb/app
“`
解压后 /fgedudb/app 下包含 bin、lib、s-hare 等目录,bin 目录内有 gs_ctl、gs_initdb、gsql、gs_dump、gs_probackup 等工具。
**步骤 2:配置 fgedu 用户环境变量。** 编辑 ~/.bas-hrc:
“`bas-h
cat >> ~/.bas-hrc << ‘EOF’
# openGauss 环境变量
export PGDATA=/fgedudb/data
export PGPORT=5432
export PATH=/fgedudb/app/bin:$PATH
export LD_LIBRARY_PATH=/fgedudb/app/lib:$LD_LIBRARY_PATH
EOF
source ~/.bas-hrc
which gs_initdb gsql gs_ctl
“`
**步骤 3:初始化数据目录。** 使用 gs_initdb 指定数据目录、编码、初始管理员用户与密码:
“`bas-h
gs_initdb -D /fgedudb/data -E UTF8 –locale=C -U fgedu -W ‘Fgedu@2026’ \
–nodename=fgedu-net-cn1 –pwprompt
“`
参数说明:-D 指定数据目录;-E UTF8 指定数据库编码;–locale=C 避免排序规则差异;-U fgedu 指定初始系统管理员用户;-W 指定初始用户密码;–nodename 记录节点名。初始化完成后终端会打印启动命令与初始提示,数据目录下生成 postgresql.conf、pg_hba.conf、pg_ident.conf 等配置文件。
初始化过程中 gs_initdb 会依次完成:生成系统表空间与模板库 template0/template1、创建初始系统目录、生成默认配置文件、设置初始管理员密码哈希、写入启动引导记录。终端最后一行提示可以直接复制的 gs_ctl start 命令。学习者应留意:初始化只执行一次,重复初始化会覆盖数据目录;若初始化中途失败,必须清空 /fgedudb/data 后重新执行,不能在残留目录上二次初始化,否则系统表与配置不一致。
初始化后数据目录的关键子目录:base 存放各数据库的数据文件;pg_wal 存放 WAL 段;pg_xlog 软链或归档引用;global 存放共享系统表;pg_audit 存放审计日志;log 存放运行日志;pg_stat 与 pg_stat_tmp 存放统计快照。
**步骤 4:按 64GB/8CPU 规格修改 postgresql.conf。** 编辑 /fgedudb/data/postgresql.conf,关键参数如下:
风哥教程 113257174
“`ini
# 监听与连接
listen_addresses = ‘*’
port = 5432
max_connections = 500
# 内存规划(64GB 物理内存)
s-hared_buffers = 16GB
effective_cache_size = 48GB
work_mem = 64MB
maintenance_work_mem = 2GB
# 并行(8 CPU)
max_worker_processes = 16
max_parallel_workers = 8
max_parallel_workers_per_gather = 4
# WAL 与检查点
wal_buffers = 64MB
max_wal_size = 16GB
min_wal_size = 2GB
checkpoint_completion_target = 0.9
wal_writer_delay = 200ms
# 复制(为实战六预留)
wal_level = replica
max_wal_senders = 8
max_replication_slots = 8
wal_keep_segments = 64
hot_standby = on
# 归档(为实战五、实战六预留)
archive_mode = on
archive_command = ‘cp %p /fgedudb/backup/archive/%f’
archive_timeout = 300
# 日志与慢查询
logging_collector = on
log_directory = ‘log’
log_filename = ‘opengauss-%Y-%m-%d_%H%M%S.log’
log_min_duration_statement = 1000
log_line_prefix = ‘%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ‘
track_activity_query_size = 2048
# 密码与安全
password_encryption_type = 1
“`
先创建归档目录:
“`bas-h
mkdir -p /fgedudb/backup/archive
chown fgedu:dba /fgedudb/backup/archive
“`
**步骤 5:配置 pg_hba.conf 认证规则。** 编辑 /fgedudb/data/pg_hba.conf,在文件末尾追加:
“`ini
# 本机本地连接
local all fgedu trust
# 主备节点网段免密(实验环境;生产改 s-ha256)
host all fgedu 192.168.10.11/32 trust
host all fgedu 192.168.10.12/32 trust
# 复制连接
host replication fgedu 192.168.10.11/32 trust
host replication fgedu 192.168.10.12/32 trust
# 应用网段
host all all 192.168.10.0/24 s-ha256
“`
**步骤 6:启动实例并验证。**
“`bas-h
gs_ctl start -D /fgedudb/data
gs_ctl status -D /fgedudb/data
“`
连接数据库:
“`bas-h
gsql -d postgres -U fgedu -h fgedu-net-cn1 -p 5432 -W ‘Fgedu@2026’
“`
进入 gsql 后创建业务数据库 fgedudb:
“`sql
CREATE DATABASE fgedudb OWNER fgedu ENCODING ‘UTF8’;
\l
\q
“`
再次以业务库连接验证:
“`bas-h
gsql -d fgedudb -U fgedu -h fgedu-net-cn1 -p 5432 -W ‘Fgedu@2026’
SELECT version();
SELECT current_database(), current_user;
\q
“`
**步骤 7:注册 systemd 托管(可选,生产推荐)。** 为避免登录会话退出后实例被 SIGHUP 影响,可把实例注册为系统服务:
“`bas-h
cat > /etc/systemd/system/opengauss.service << ‘EOF’
[Unit]
Description=openGauss fgedudb
After=network.target
[Service]
Type=forking
User=fgedu
Group=dba
Environment=PGDATA=/fgedudb/data
ExecStart=/fgedudb/app/bin/gs_ctl start -D /fgedudb/data
ExecStop=/fgedudb/app/bin/gs_ctl stop -D /fgedudb/data -m fast
ExecReload=/fgedudb/app/bin/gs_ctl reload -D /fgedudb/data
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable opengauss
“`
注意:systemd 启动与手动 gs_ctl 二选一,不要同时用两种方式管理同一实例,否则会出现 pid 文件冲突。
**步骤 8:查看启动日志与版本信息。** 实例日志位于 /fgedudb/data/log,启动成功的标志是日志末尾出现 database system is ready to accept connections:
“`bas-h
ls -lt /fgedudb/data/log/ | head
tail -50 /fgedudb/data/log/$(ls -t /fgedudb/data/log/ | head -1)
“`
在 gsql 内查看运行参数摘要:
“`sql
s-hOW data_directory;
s-hOW config_file;
s-hOW hba_file;
s-hOW port;
SELECT pg_postmaster_start_time();
“`
### 实战三:基础管理操作(用户、权限、表、索引、事务、锁)
**步骤 1:实例启停与参数动态生效。** 常用生命周期命令:
“`bas-h
gs_ctl start -D /fgedudb/data
gs_ctl stop -D /fgedudb/data -m fast
gs_ctl restart -D /fgedudb/data -m fast
gs_ctl reload -D /fgedudb/data
“`
使用 gs_guc 在线修改参数并生效,无需重启:
风哥数据库教程 itpux-com
“`bas-h
gs_guc reload -D /fgedudb/data -c “log_min_duration_statement = 500”
gs_guc set -D /fgedudb/data -c “max_connections = 600”
“`
查看当前参数值:
“`bas-h
gsql -d fgedudb -U fgedu -c “s-hOW s-hared_buffers;”
gsql -d fgedudb -U fgedu -c “s-hOW max_connections;”
“`
**步骤 2:角色与用户、授权。** 进入 gsql:
“`bas-h
gsql -d fgedudb -U fgedu
“`
创建业务角色并授权:
“`sql
— 创建只读角色与读写角色
CREATE ROLE ro_role LOGIN PASSWORD ‘Ro@2026’;
CREATE ROLE rw_role LOGIN PASSWORD ‘Rw@2026’;
— 创建业务用户并继承角色
CREATE USER app_read LOGIN PASSWORD ‘AppRead@2026’;
CREATE USER app_write LOGIN PASSWORD ‘AppWrite@2026’;
GRANT ro_role TO app_read;
GRANT rw_role TO app_write;
— 创建模式并授权
CREATE SCHEMA app AUTHORIZATION fgedu;
GRANT USAGE ON SCHEMA app TO ro_role, rw_role;
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT SELECT ON TABLES TO ro_role;
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO rw_role;
— 查看角色成员
\du
“`
**步骤 3:建表、索引与约束,灌入测试数据。**
“`sql
— 建表
CREATE TABLE app.t_order (
order_id bigint PRIMARY KEY,
cust_id bigint NOT NULL,
order_amount numeric(12,2) NOT NULL DEFAULT 0,
order_status smallint NOT NULL DEFAULT 0,
create_time timestamp NOT NULL DEFAULT now()
) DISTRIBUTE BY HAs-h(order_id);
CREATE TABLE app.t_cust (
cust_id bigint PRIMARY KEY,
cust_name varchar(64) NOT NULL,
city varchar(32),
reg_time timestamp DEFAULT now()
);
— 索引
CREATE INDEX idx_order_cust ON app.t_order(cust_id);
CREATE INDEX idx_order_status_time ON app.t_order(order_status, create_time DESC);
— 灌入测试数据
INSERT INTO app.t_cust(cust_id, cust_name, city)
SELECT generate_series(1, 10000), ‘cust_’ || gs, ‘chengdu’
FROM generate_series(1, 10000) AS gs;
INSERT INTO app.t_order(order_id, cust_id, order_amount, order_status)
SELECT gs, (random()*9999+1)::bigint, round((random()*5000)::numeric,2),
(random()*3)::smallint
FROM generate_series(1, 100000) AS gs;
ANALYZE app.t_order;
ANALYZE app.t_cust;
“`
验证数据与执行计划:
“`sql
SELECT count(*) FROM app.t_order;
EXPLAIN ANALYZE SELECT o.order_id, c.cust_name, o.order_amount
FROM app.t_order o JOIN app.t_cust c ON o.cust_id = c.cust_id
WHERE o.order_status = 1 ORDER BY o.create_time DESC LIMIT 20;
“`
**步骤 4:事务与锁观察。** 新开一个 gsql 会话 A 开启事务并更新一行不提交:
“`sql
BEGIN;
UPDATE app.t_order SET order_amount = order_amount + 10 WHERE order_id = 1;
— 不要 COMMIT
“`
会话 B 查询同一行:
“`sql
SELECT * FROM app.t_order WHERE order_id = 1;
“`
会话 B 会被行锁阻塞。会话 A 执行 COMMIT 后阻塞解除。查看锁等待:
“`sql
SELECT blocked.pid AS blocked_pid, blocked.query AS blocked_query,
holding.pid AS holding_pid, holding.query AS holding_query
FROM pg_locks bl
JOIN pg_stat_activity blocked ON bl.pid = blocked.pid
JOIN pg_locks hl ON bl.relation = hl.relation AND bl.pid != hl.pid
JOIN pg_stat_activity holding ON hl.pid = holding.pid
WHERE NOT bl.granted;
“`
**步骤 5:查看会话与统计信息。**
“`sql
— 当前活动会话
SELECT pid, usename, state, wait_event_type, wait_event, query
FROM pg_stat_activity WHERE datname = ‘fgedudb’ ORDER BY query_start;
— 表级统计:死元组、上次 vacuum
SELECT relname, n_live_tup, n_dead_tup, last_autovacuum, last_analyze
FROM pg_stat_user_tables WHERE schemaname = ‘app’;
— 数据库级统计
SELECT datname, numbackends, xact_commit, xact_rollback, blks_read, blks_hit
FROM pg_stat_database WHERE datname = ‘fgedudb’;
“`
**步骤 6:序列、视图与搜索路径。** 创建自增序列并在视图中封装常用查询:
网上搜索风哥教程可以学习全套数据库教程
“`sql
CREATE SEQUENCE app.seq_order START 1000001 INCREMENT 1 CACHE 100;
SELECT nextval(‘app.seq_order’);
CREATE OR REPLACE VIEW app.v_order_summary AS
SELECT o.order_status, count(*) AS order_cnt, sum(o.order_amount) AS total_amt
FROM app.t_order o GROUP BY o.order_status;
— 设置会话搜索路径,省略模式名
SET search_path TO app, public;
SELECT * FROM v_order_summary LIMIT 5;
— 回收权限示例:撤销只读角色的写权限
REVOKE INSERT, UPDATE, DELETE ON app.t_order FROM ro_role;
\du ro_role
“`
**步骤 7:表空间与物理分布。** 在实验目录下建表空间,把大表迁出默认表空间:
“`sql
CREATE TABLESPACE ts_order LOCATION ‘/fgedudb/data/tbs’;
ALTER TABLE app.t_order SET TABLESPACE ts_order;
SELECT tablename, tablespace FROM pg_tables WHERE schemaname = ‘app’;
“`
**步骤 8:常用 gsql 元命令速查。** 教学中频繁使用的元命令汇总,便于学习者查表:
“`sql
\l — 列出全部数据库
\dn — 列出模式
\dt app.* — 列出 app 模式下的表
\di — 列出索引
\du — 列出角色
\db — 列出表空间
\df — 列出函数
\timing on — 开启语句计时
\x — 开启扩展竖排显示
\e — 打开编辑器写 SQL
\q — 退出
“`
**步骤 9:约束、函数与事务隔离演示。** 给订单表补约束并编写一个简单的库存扣减函数:
“`sql
ALTER TABLE app.t_order ADD CONSTRAINT c-h-k_amount CHECK (order_amount >= 0);
CREATE OR REPLACE FUNCTION app.f_calc_total(p_status smallint)
RETURNS numeric AS $$
DECLARE
v_total numeric;
BEGIN
SELECT COALESCE(sum(order_amount), 0) INTO v_total
FROM app.t_order WHERE order_status = p_status;
RETURN v_total;
END;
$$ LANGUAGE plpgsql;
SELECT app.f_calc_total(1);
“`
演示事务隔离级别差异:会话 A 开启可重复读事务并读取一次,会话 B 更新并提交,会话 A 再次读取仍是旧值:
上51CTO搜索风哥可以学习全套数据库教程
“`sql
— 会话 A
START TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT count(*) FROM app.t_order;
— 会话 B 执行 UPDATE app.t_order SET order_status = 2 WHERE order_id = 1; COMMIT;
— 会话 A 再次查询 count(*),结果与第一次一致
COMMIT;
“`
在同一事务内对比 read committed 则会看到新提交的行数,学习者亲手对比一次即可理解快照边界。
### 实战四:逻辑备份与恢复(gs_dump / gs_dumpall / gs_restore)
**步骤 1:单库逻辑备份。** 以 fgedu 用户执行,导出 fgedudb 数据库为自定义压缩格式:
“`bas-h
mkdir -p /fgedudb/backup/logical
gs_dump -U fgedu -h fgedu-net-cn1 -p 5432 -d fgedudb \
-F c -f /fgedudb/backup/logical/fgedudb_$(date +%Y%m%d).dump \
-n app –verbose
“`
参数说明:-F c 使用自定义归档格式(支持并行恢复与选择性恢复);-n app 只导出 app 模式;-f 指定输出文件。导出纯文本 SQL 格式用于跨版本迁移:
“`bas-h
gs_dump -U fgedu -h fgedu-net-cn1 -p 5432 -d fgedudb \
-F p -f /fgedudb/backup/logical/fgedudb_$(date +%Y%m%d).sql \
–schema-only
“`
**步骤 2:全库导出(含角色、表空间)。** gs_dumpall 导出实例内全部数据库与全局对象:
“`bas-h
gs_dumpall -U fgedu -h fgedu-net-cn1 -p 5432 \
-f /fgedudb/backup/logical/all_$(date +%Y%m%d).sql –globals-only
“`
–globals-only 只导出角色、表空间、权限等全局定义,不导出业务数据;去掉该参数则导出全库数据。跨版本迁移时通常先 gs_dumpall –globals-only 建角色,再 gs_dump 逐库导出数据,恢复时先执行全局脚本再恢复各库。
**步骤 3:模拟误删并恢复。** 先在 gsql 中误删表:
“`sql
DROP TABLE app.t_order;
\dt app.
“`
使用自定义格式备份恢复单表:
“`bas-h
gs_restore -U fgedu -h fgedu-net-cn1 -p 5432 -d fgedudb \
/fgedudb/backup/logical/fgedudb_$(date +%Y%m%d).dump \
-n app -t t_order –verbose
“`
恢复纯文本 SQL 备份使用 gsql:
“`bas-h
gsql -d fgedudb -U fgedu -f /fgedudb/backup/logical/fgedudb_$(date +%Y%m%d).sql
“`
验证:
“`bas-h
gsql -d fgedudb -U fgedu -c “SELECT count(*) FROM app.t_order;”
“`
**步骤 4:配置定时逻辑备份。** 编辑 fgedu 用户 crontab:
风哥 itpux-com
“`bas-h
crontab -e
“`
加入每日凌晨 2 点全库逻辑备份、保留 30 天的任务:
“`cron
0 2 * * * /fgedudb/app/bin/gs_dump -U fgedu -h 127.0.0.1 -p 5432 -d fgedudb -F c -f /fgedudb/backup/logical/fgedudb_$(date +\%Y\%m\%d).dump && find /fgedudb/backup/logical -name “fgedudb_*.dump” -mtime +30 -delete
“`
**步骤 5:备份清单查看与并行恢复。** gs_restore 可先列出自定义归档内的对象,不执行恢复:
“`bas-h
gs_restore -l /fgedudb/backup/logical/fgedudb_$(date +%Y%m%d).dump
“`
大库恢复使用并行线程缩短窗口:
“`bas-h
gs_restore -U fgedu -h fgedu-net-cn1 -p 5432 -d fgedudb \
-j 4 –no-owner –role=rw_role \
/fgedudb/backup/logical/fgedudb_$(date +%Y%m%d).dump
“`
参数:-j 4 并行恢复;–no-owner 忽略原对象属主,由 –role 指定角色接管;仅恢复指定表时加 -t 表名。恢复完成后核对行数:
“`bas-h
gsql -d fgedudb -U fgedu -c “SELECT count(*) FROM app.t_order;”
“`
### 实战五:物理备份与时间点恢复(gs_probackup)
**步骤 1:初始化备份目录与实例。** 以 fgedu 用户执行:
“`bas-h
gs_probackup init -B /fgedudb/backup/physical
gs_probackup add-instance -B /fgedudb/backup/physical \
-D /fgedudb/data –instance=fgedudb
“`
**步骤 2:配置备份策略。** 设置保留冗余份数、WAL 深度与压缩:
“`bas-h
gs_probackup set-config -B /fgedudb/backup/physical –instance=fgedudb \
–retention-redundancy=7 –wal-depth=3 \
–compress-algorithm=zlib –compress-level=6 \
-d fgedudb -h 127.0.0.1 -p 5432 -U fgedu
“`
查看配置:
“`bas-h
gs_probackup s-how-config -B /fgedudb/backup/physical –instance=fgedudb
“`
**步骤 3:创建全量备份。**
“`bas-h
gs_probackup backup -B /fgedudb/backup/physical –instance=fgedudb \
-b FULL –backup-pg-log -j 4 –progress
“`
参数:-b FULL 全量备份;-j 4 并行线程数;–backup-pg-log 同时备份日志目录。
**步骤 4:创建 PTRACK 增量备份。** 先在 postgresql.conf 开启块变更跟踪:
“`bas-h
gs_guc reload -D /fgedudb/data -c “enable_cbm_tracking = on”
“`
等待一段时间产生变更后执行增量:
“`bas-h
gs_probackup backup -B /fgedudb/backup/physical –instance=fgedudb \
-b PTRACK –temp-slot -j 4 –progress
“`
查看备份集:
“`bas-h
gs_probackup s-how -B /fgedudb/backup/physical –instance=fgedudb
“`
**步骤 5:验证备份可恢复。**
“`bas-h
gs_probackup validate -B /fgedudb/backup/physical –instance=fgedudb
“`
**步骤 6:模拟故障并执行 PITR。** 先记录当前时间作为恢复目标:
“`bas-h
date ‘+%Y-%m-%d %H:%M:%S’
“`
在 gsql 中制造误操作:
“`sql
DROP TABLE app.t_cust;
“`
停止实例,还原最近全量备份:
“`bas-h
gs_ctl stop -D /fgedudb/data -m fast
gs_probackup restore -B /fgedudb/backup/physical –instance=fgedudb \
-D /fgedudb/data –recovery-target-time=’2026-11-10 10:00:00′ \
–recovery-target-inclusive=true –force –progress
“`
启动实例进入恢复模式,重放归档 WAL 到目标时间:
“`bas-h
gs_ctl start -D /fgedudb/data
“`
连接后确认表已恢复到目标时刻:
“`bas-h
gsql -d fgedudb -U fgedu -c “SELECT count(*) FROM app.t_cust;”
“`
恢复完成后执行:
“`sql
SELECT pg_xlog_replay_resume();
“`
**步骤 7:按 LSN、事务 ID、备份集名恢复。** 除时间点外,gs_probackup 还支持以 LSN、事务 ID、备份集名称为恢复目标。先从备份清单记录可用目标:
“`bas-h
gs_probackup s-how -B /fgedudb/backup/physical –instance=fgedudb
“`
按 LSN 精确恢复(避免恢复到误操作事务之后):
风哥教程 113257174
“`bas-h
gs_probackup restore -B /fgedudb/backup/physical –instance=fgedudb \
-D /fgedudb/data –recovery-target-lsn=’0/1A2B3C00′ \
–recovery-target-inclusive=false –force
“`
按事务 ID 恢复:
“`bas-h
gs_probackup restore -B /fgedudb/backup/physical –instance=fgedudb \
-D /fgedudb/data –recovery-target-xid=’82134′ –force
“`
按命名备份集恢复:
“`bas-h
gs_probackup restore -B /fgedudb/backup/physical –instance=fgedudb \
-D /fgedudb/data –recovery-target-name=’FULL-20261110-020000′ –force
“`
**步骤 8:外部目录备份与保留策略清理。** 备份集外的配置目录、应用程序目录可通过 –external-dirs 纳入备份:
“`bas-h
gs_probackup backup -B /fgedudb/backup/physical –instance=fgedudb \
-b FULL –external-dirs=/fgedudb/backup/archive –progress
“`
按 retention-redundancy 自动清理过期备份集:
“`bas-h
gs_probackup delete -B /fgedudb/backup/physical –instance=fgedudb \
–delete-expired –delete-wal –progress
“`
**步骤 9:归档策略。** archive_command 把 WAL 复制到 /fgedudb/backup/archive,归档目录必须独立于数据盘并定期清理,命令示例:
“`bas-h
find /fgedudb/backup/archive -mtime +21 -type f -delete
“`
清理归档前先确认最新全量备份已经落盘,否则 PITR 会因缺少中间段日志而失败。
**步骤 10:恢复演练检查清单。** 备份不演练等于没有备份,每季度应在隔离环境执行一次完整恢复,核对以下项目:备份集 validate 通过;还原后数据目录权限属主为 fgedu;recovery 配置指向正确归档目录;启动后 pg_is_in_recovery() 状态符合预期;目标表行数与源库对账一致;序列当前值、视图定义、函数对象完整;恢复完成后及时清理演练实例,避免与生产混淆。
### 实战六:一主一备流复制搭建(fgedu-net-cn1 主、fgedu-net-cn2 备)
**步骤 1:备节点安装同版本软件。** 在 fgedu-net-cn2 上重复实战一的用户、目录、依赖、免密准备,并解压相同安装包到 /fgedudb/app,配置相同的 ~/.bas-hrc 环境变量。备节点不需要 gs_initdb 初始化,数据目录将由主节点备份拉取。
**步骤 2:主节点复制参数与认证。** 主节点 postgresql.conf 已在实战二配置 wal_level=replica、max_wal_senders=8、max_replication_slots=8、hot_standby=on。补充同步复制参数:
“`bas-h
gs_guc reload -D /fgedudb/data -c “synchronous_standby_names = ‘fgedu-net-cn2′”
“`
pg_hba.conf 已在实战二放通 192.168.10.12 的 replication 连接。
**步骤 3:主节点创建复制角色与复制槽。**
“`bas-h
gsql -d fgedudb -U fgedu
“`
“`sql
CREATE ROLE repl_user LOGIN REPLICATION PASSWORD ‘Repl@2026’;
CREATE_REPLICATION_SLOT repl_slot_cn2 PHYSICAL;
“`
查看复制槽:
“`sql
SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;
\q
“`
**步骤 4:备节点使用 gs_basebackup 拉取基础备份。** 在 fgedu-net-cn2 上以 fgedu 用户执行,先清空空数据目录:
“`bas-h
rm -rf /fgedudb/data/*
gs_basebackup -D /fgedudb/data -h fgedu-net-cn1 -p 5432 \
-U repl_user -W ‘Repl@2026’ -X stream -R -P -j 4
“`
参数:-X stream 备份同时流式传输 WAL;-R 自动在数据目录写入 primary_conninfo 等恢复配置;-P 显示进度;-j 4 并行。
**步骤 5:修改备节点配置。** 编辑 /fgedudb/data/postgresql.conf:
“`ini
port = 5432
hot_standby = on
primary_conninfo = ‘host=fgedu-net-cn1 port=5432 user=repl_user password=Repl@2026 application_name=fgedu-net-cn2’
“`
备节点 pg_hba.conf 与主节点保持一致。
**步骤 6:启动备节点并验证复制状态。**
“`bas-h
gs_ctl start -D /fgedudb/data
“`
在主节点查看复制视图:
“`bas-h
gsql -d fgedudb -U fgedu -c “SELECT pid, usename, application_name, client_addr, state, sync_state, sent_lsn, replay_lsn FROM pg_stat_replication;”
“`
正常输出中 application_name 为 fgedu-net-cn2,state 为 streaming,sync_state 为 sync(同步模式)。在主节点写入测试数据:
“`sql
CREATE TABLE app.t_repl_test(id int, info varchar(32));
INSERT INTO app.t_repl_test VALUES (1, ‘primary write’);
“`
在备节点只读查询验证同步:
“`bas-h
gsql -d fgedudb -U fgedu -h fgedu-net-cn2 -c “SELECT * FROM app.t_repl_test;”
“`
备节点尝试写入应被拒绝:
“`sql
INSERT INTO app.t_repl_test VALUES (2, ‘standby write’);
— 报错:cannot execute INSERT in a read-only transaction
“`
**步骤 7:计划内主备切换(switchover)。** 在主节点执行优雅切换:
风哥数据库教程 itpux-com
“`bas-h
gs_ctl switchover -D /fgedudb/data -m fast
“`
切换后 fgedu-net-cn2 提升为主,fgedu-net-cn1 降级为备。分别在两台机器查看角色:
“`bas-h
gsql -d fgedudb -U fgedu -c “SELECT pg_is_in_recovery();”
“`
返回 false 为新主,返回 true 为备。
**步骤 8:故障场景提升与重建。** 模拟主节点宕机,在备节点执行提升:
“`bas-h
gs_ctl promote -D /fgedudb/data
“`
原主修复后,不能直接以旧主身份启动,需重新以备节点身份加入:清空旧主数据目录,重复步骤 4 的 gs_basebackup 拉取新主备份,再启动并验证 pg_stat_replication。
**步骤 9:监控复制延迟。** 在主节点定期执行:
“`sql
SELECT application_name,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_delay_bytes,
now() – reply_time AS reply_age
FROM pg_stat_replication;
“`
**步骤 10:同步模式与提交级别。** synchronous_standby_names 的写法决定参与同步的备库数量:’fgedu-net-cn2′ 表示任意一个指定备库确认即可;’ANY 1 (fgedu-net-cn2, fgedu-net-cn3)’ 表示多备库中任意一个确认即提交;’FIRST 1 (…)’ 表示按顺序取第一个。同步强度由 synchronous_commit 控制:on 表示等待备库写盘确认;remote_write 只等备库写内存;off 为异步。生产金融场景用 on,通用业务可按容忍度调级:
“`bas-h
gs_guc reload -D /fgedudb/data -c “synchronous_commit = on”
gs_guc reload -D /fgedudb/data -c “synchronous_standby_names = ‘ANY 1 (fgedu-net-cn2)'”
“`
**步骤 11:在线扩容第三个备库(简述)。** 已有一主一备时新增备库,先在新节点完成实战一的环境准备,再从主节点 gs_basebackup 拉取,创建新的复制槽并配置 primary_conninfo,启动后在主节点 pg_stat_replication 中应看到多条记录。本套风哥教程以一主一备为演练目标,扩容命令同步骤 4,仅替换槽名与应用名。
**步骤 12:废弃复制槽的处理。** 备库YJ下线后,对应槽若不删除会持续保留 WAL 撑爆磁盘:
“`sql
SELECT slot_name, active, pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)
FROM pg_replication_slots;
DROP_REPLICATION_SLOT repl_slot_cn2;
“`
**步骤 13:切换后验证清单。** 无论 switchover 还是 promote,切换完成后必须逐项核对:新主 pg_is_in_recovery() 返回 false;新主可读写业务表;旧主以备库身份重新接入后 pg_stat_replication 出现对应记录;应用连接串指向新主 VIP 或新 IP;复制延迟在分钟级内收敛;备份任务在新主上重新注册。切换前应记录原主 LSN,切换后比对确认无事务丢失。
### 实战七:安全加固(认证、密码策略、审计、SSL)
**步骤 1:收紧 pg_hba.conf 认证方式。** 实验阶段使用 trust 仅用于连通,生产环境必须改为 s-ha256。编辑主备两端 /fgedudb/data/pg_hba.conf:
“`ini
# 本机管理连接保留 scram/s-ha256
local all fgedu s-ha256
# 应用网段强制 s-ha256
host all all 192.168.10.0/24 s-ha256
# 复制连接使用复制专用账号
host replication repl_user 192.168.10.11/32 s-ha256
host replication repl_user 192.168.10.12/32 s-ha256
“`
重载生效:
“`bas-h
gs_ctl reload -D /fgedudb/data
“`
**步骤 2:密码复杂度与过期策略。** 修改 postgresql.conf:
网上搜索风哥教程可以学习全套数据库教程
“`bas-h
gs_guc reload -D /fgedudb/data -c “password_encryption_type = 1”
gs_guc reload -D /fgedudb/data -c “password_policy = 1”
gs_guc reload -D /fgedudb/data -c “failed_login_attempts = 5”
gs_guc reload -D /fgedudb/data -c “password_lock_time = 1d”
gs_guc reload -D /fgedudb/data -c “password_expiration = 90”
“`
password_policy=1 要求密码包含大写、小写、数字、特殊字符四类中的至少三类;failed_login_attempts 限制连续失败次数,超限锁定。
**步骤 3:开启审计。**
“`bas-h
gs_guc reload -D /fgedudb/data -c “audit_enabled = 1”
gs_guc reload -D /fgedudb/data -c “audit_login_logout = 1”
gs_guc reload -D /fgedudb/data -c “audit_dml_state = 1”
gs_guc reload -D /fgedudb/data -c “audit_dml_state_select = 1”
gs_guc reload -D /fgedudb/data -c “audit_system_object = 1”
“`
审计日志默认位于 /fgedudb/data/pg_audit/,查看:
“`bas-h
ls -lt /fgedudb/data/pg_audit/ | head
grep ‘LOGIN’ /fgedudb/data/pg_audit/*.csv | tail -20
“`
**步骤 4:最小权限复核。** 定期检查公共权限与角色成员:
“`sql
— 检查 PUBLIC 是否被授予表权限
SELECT grantee, table_schema, table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = ‘PUBLIC’;
— 检查具备超级用户的角色
SELECT rolname, rolsuper, rolcreaterole, rolcreatedb
FROM pg_roles WHERE rolsuper = true;
“`
**步骤 5:SSL 加密传输(简述)。** 生成证书后在 postgresql.conf 配置 ssl=on、ssl_cert_file、ssl_key_file,pg_hba.conf 对应行使用 hostssl,应用连接串追加 sslmode=verify-ca。本实验环境以内网为主,仅记录配置项,不展开证书签发流程。
**步骤 6:连接数与会话配额。** 按 500 连接基线,为业务角色单独设上限,防止单个应用占满连接:
“`sql
ALTER ROLE rw_role CONNECTION LIMIT 100;
ALTER ROLE ro_role CONNECTION LIMIT 200;
SELECT rolname, rolconnlimit FROM pg_roles WHERE rolconnlimit <> -1;
“`
查看当前连接占用:
“`sql
SELECT usename, count(*) FROM pg_stat_activity
WHERE datname = ‘fgedudb’ GROUP BY usename ORDER BY 2 DESC;
“`
### 实战八:监控与性能优化
**步骤 1:慢查询采集。** postgresql.conf 已设置 log_min_duration_statement=1000(超过 1 秒记录)。调整为 500 毫秒:
“`bas-h
gs_guc reload -D /fgedudb/data -c “log_min_duration_statement = 500”
“`
提取慢 SQL:
上51CTO搜索风哥可以学习全套数据库教程
“`bas-h
grep ‘duration:’ /fgedudb/data/log/*.log | sort -t= -k2 -rn | head -20
“`
**步骤 2:执行计划分析。** 对慢 SQL 使用 EXPLAIN ANALYZE:
“`sql
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT o.order_id, c.cust_name, o.order_amount
FROM app.t_order o JOIN app.t_cust c ON o.cust_id = c.cust_id
WHERE o.order_status = 1 ORDER BY o.create_time DESC LIMIT 20;
“`
判断要点:出现 Seq Scan 且行数巨大说明缺索引;Rows Removed by Filter 比例过高说明谓词选择差;Sort Method: External Merge Disk 说明 work_mem 不足导致落盘,应适当调大 work_mem 或拆分查询。
**步骤 3:统计信息维护。**
“`sql
— 手动收集
ANALYZE VERBOSE app.t_order;
— 查看统计信息新鲜度
SELECT relname, last_analyze, last_autoanalyze, n_live_tup, n_dead_tup
FROM pg_stat_user_tables WHERE schemaname = ‘app’;
“`
**步骤 4:索引体检。** 查找未使用索引与重复索引:
“`sql
— 未使用索引
SELECT schemaname, relname, indexrelname, idx_scan
FROM pg_stat_user_indexes
WHERE schemaname = ‘app’ AND idx_scan = 0;
— 索引大小
SELECT relname, indexrelname, pg_size_pretty(pg_relation_size(indexrelid))
FROM pg_stat_user_indexes WHERE schemaname = ‘app’
ORDER BY pg_relation_size(indexrelid) DESC;
“`
对低频写入、高频查询的表补复合索引;对长期零扫描的冗余索引评估删除。
复合索引遵循最左前缀原则:索引 (order_status, create_time DESC) 可服务于按状态过滤并按时间排序的查询,但不能直接服务于仅按 create_time 过滤的查询。为避免索引滥用,先看慢 SQL 的谓词与排序字段再建索引,不要为每个查询单独建一个索引,写放大与维护成本会随索引数量线性上升。覆盖索引可把查询需要的列一并纳入,避免回表:
“`sql
CREATE INDEX idx_order_status_time_cover ON app.t_order(order_status, create_time DESC)
INCLUDE (cust_id, order_amount);
“`
**步骤 4b:统计信息与执行计划联动。** 当 EXPLAIN ANALYZE 显示估算行数与真实行数相差十倍以上,先执行 ANALYZE 再复跑计划,多数错误计划会自动纠正;若统计信息新鲜仍选错计划,再考虑调整索引或用 hint 干预,不要在统计信息过期时直接改参数。
**步骤 5:vacuum 与膨胀治理。**
“`sql
— 查看膨胀严重的表
SELECT relname, n_dead_tup, n_live_tup,
round(100.0 * n_dead_tup / NULLIF(n_live_tup,0), 2) AS dead_pct
FROM pg_stat_user_tables
WHERE schemaname = ‘app’ AND n_dead_tup > 1000;
“`
手动 vacuum 与分析:
“`bas-h
gsql -d fgedudb -U fgedu -c “VACUUM (ANALYZE, VERBOSE) app.t_order;”
“`
对长期膨胀的大表可在业务低峰执行 VACUUM FULL(会锁表,需评估窗口)。
**步骤 6:资源池限制大查询。** 创建资源池限制并发与内存:
“`sql
CREATE RESOURCE POOL rp_report
WITH (mem_percent = 20, active_statements = 4, max_worker_groups = 2);
ALTER ROLE rw_role RESOURCE POOL rp_report;
“`
**步骤 7:使用 gs_checkperf 采集性能快照。**
“`bas-h
gs_checkperf -U fgedu -d fgedudb -p 5432 -i kmc -o /fgedudb/backup/perf_$(date +%Y%m%d)
“`
输出包含 CPU、内存、IO、缓存命中率的基线对比,用于容量评估。
**步骤 8:缓存命中率与 IO 基线。** 缓冲池命中率应长期保持在 99% 以上,低于该值说明 s-hared_buffers 不足或访问模式离散:
“`sql
SELECT round(100.0 * sum(blks_hit) / NULLIF(sum(blks_hit + blks_read), 0), 2)
AS cache_hit_ratio
FROM pg_stat_database WHERE datname = ‘fgedudb’;
“`
表级 IO 分布,定位热点表:
“`sql
SELECT relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit
FROM pg_stat_user_tables WHERE schemaname = ‘app’
ORDER BY heap_blks_read DESC LIMIT 10;
“`
**步骤 9:连接池与长连接策略。** 应用侧建议使用连接池(如 pgbouncer 或自研池化)复用连接,避免每次请求新建会话消耗 fork/线程资源;数据库侧通过 max_connections=500 兜底,配合会话空闲超时自动回收:
“`bas-h
gs_guc reload -D /fgedudb/data -c “idle_in_transaction_session_timeout = 60000”
gs_guc reload -D /fgedudb/data -c “lock_timeout = 5000”
“`
idle_in_transaction_session_timeout 终止长时间挂起的事务,避免其持锁阻塞 vacuum;lock_timeout 让等待锁超过 5 秒的语句主动报错,而不是无限堆积。
### 实战九:常见故障诊断流程
**故障一:连接被拒绝。** 依次排查:实例是否启动(gs_ctl status)、端口是否监听(ss -lntp | grep 5432)、pg_hba.conf 是否放通来源 IP、防火墙是否拦截。典型报错与定位命令:
“`bas-h
gs_ctl status -D /fgedudb/data
ss -lntp | grep 5432
tail -100 /fgedudb/data/log/*.log
“`
**故障二:启动失败。** 查看日志最后段,常见原因是配置参数拼写错误、数据目录权限不对、上一次未干净退出残留 postmaster.pid:
“`bas-h
tail -200 /fgedudb/data/log/postgresql-*.log
ls -l /fgedudb/data/postmaster.pid
“`
确认是上次崩溃残留时,先执行 gs_ctl stop -m immediate,再删除残留 pid 文件后启动。
**故障三:WAL 堆积导致磁盘满。** 复制槽长期未消费会使主节点保留大量 WAL:
“`sql
SELECT slot_name, active, restart_lsn,
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS retained_bytes
FROM pg_replication_slots;
“`
备节点断连修复后槽自动推进;确认废弃的槽可执行 DROP_REPLICATION_SLOT ‘slot_name’,但删除前必须确认对应备库不再使用。
**故障四:主备断连后追不上。** 查看 pg_stat_replication 的 state 是否为 catchup,对比 sent_lsn 与 replay_lsn 差距;网络抖动后 walsender 会自动重连,差距较大时备节点逐步回放,期间避免 promote。
**故障五:磁盘空间不足告警。** 检查数据目录与归档目录占用:
“`bas-h
du -s-h /fgedudb/data /fgedudb/backup/archive /fgedudb/backup/physical
find /fgedudb/backup/archive -mtime +14 -delete
“`
**故障六:连接数打满。** 应用报 too many connections 时,先看占用来源:
“`sql
SELECT state, count(*) FROM pg_stat_activity
WHERE datname = ‘fgedudb’ GROUP BY state;
SELECT pid, usename, state, query FROM pg_stat_activity
WHERE datname = ‘fgedudb’ AND state = ‘idle in transaction’ LIMIT 20;
“`
对异常挂起会话执行 SELECT pg_terminate_backend(pid) 释放连接,再从应用侧排查连接池配置。
**故障七:死锁检测。** 日志出现 deadlock detected 时,查看等待环:
“`sql
SELECT a.pid, a.query, b.pid AS wait_for, b.query AS wait_query
FROM pg_locks l JOIN pg_stat_activity a ON l.pid = a.pid
JOIN pg_locks w ON l.relation = w.relation AND NOT l.granted
JOIN pg_stat_activity b ON w.pid = b.pid;
“`
死锁由数据库自动回滚其中一个事务,根治办法是统一多语句的加锁顺序,避免交叉更新。
**故障八:检查点超时与 WAL 反复刷写。** 日志出现 checkpoint starting 但长期不结束,通常是 max_wal_size=16GB 不足以容纳一个检查点周期内的日志量,或磁盘 IO 饱和。先看 WAL 目录大小:
“`bas-h
du -s-h /fgedudb/data/pg_wal
ls /fgedudb/data/pg_wal | wc -l
“`
必要时调大 max_wal_size 并降低 checkpoint_completion_target 的激进程度,而不是盲目关闭检查点。
**故障九:归档失败导致 WAL 无法回收。** archive_command 返回非零会让主节点反复重试并保留 WAL,日志中出现 archive command failed。先手动执行同一条复制命令定位权限或目录问题:
“`bas-h
ls -ld /fgedudb/backup/archive
cp /fgedudb/data/pg_wal/000000010000000000000001 /fgedudb/backup/archive/
“`
修复后在 gsql 中执行 SELECT pg_switch_wal(); 触发新段归档,积压会自动追赶。
## 四、风哥针对本文总结
风哥针对本文总结如下:本套风哥教程以 openGauss 5.0.5 LTS 为载体,先在理论篇讲清了它的产品定位、线程与内存体系、MVCC、流复制、备份恢复、安全与优化的内核原理,再在实战篇按九个实验完整落地了 64GB 内存、8 CPU 规格下的环境准备、单机安装初始化、基础管理、逻辑备份、物理备份与 PITR、一主一备流复制与切换、安全加固、监控优化与故障诊断。学习者需要抓住三条主线:第一,所有配置围绕 s-hared_buffers=16GB、effective_cache_size=48GB、work_mem=64MB 的内存基线展开,参数与硬件规格必须匹配,不能照搬小内存示例;第二,备份体系要分清逻辑备份(gs_dump)用于迁移与单点恢复、物理备份(gs_probackup)配合 WAL 归档用于 PITR,两者互补而非替代;第三,流复制的核心是复制槽与 LSN 推进,同步模式保零丢失、异步模式保性能,切换前必须确认 replay_lsn 与 sent_lsn 对齐。
运维层面,风哥提醒学习者牢记:生产环境禁止 trust 认证、必须开启审计与慢查询日志、定期 vacuum 与 ANALYZE、监控复制延迟与磁盘占用,故障时先看日志再动手,优先保护数据目录。本套风哥教程的命令均已按 /fgedudb 路径、fgedudb 库名、fgedu 用户、fgedu-net-cn1/fgedu-net-cn2 主机名统一,学习者可在此基础上替换为自己的生产环境参数继续演练。国产数据库的学习没有捷径,安装一次、备份恢复一次、主备切换一次,比通读十遍文档更有效。
最后,风哥再强调三条落地纪律:第一,任何参数调整先在测试环境复现,s-hared_buffers、work_mem、max_connections 这类基线参数一旦改错会直接影响实例启动;第二,备份策略必须定期演练恢复,只备份不验证等于裸奔;第三,主备切换必须有书面预案与回退步骤,故障时靠记忆操作最容易出错。掌握本套风哥教程的单机与一主一备流程后,学习者可继续向资源池化、CM 自动仲裁、在线扩容、性能压测等方向延伸,openGauss 的官方文档与社区是后续深入的主要资料来源。
—
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
