在 openGauss 数据库管理系统中,存储管理是连接逻辑数据结构与物理硬件资源的桥梁。深入理解这一体系,对于性能调优、容量规划以及故障排查至关重要。本文将从宏观的表空间与数据库,深入到微观的数据文件与数据块,全方位解析 openGauss 的存储架构。


思维导图



一、Tablespace表空间
表空间 (Tablespace) 是 openGauss 中最高层级的逻辑存储容器。它的核心作用是将数据库的逻辑对象(表、索引等)映射到具体的文件系统目录。
1. 表空间的核心价值
I/O 性能隔离 : 管理员可以将高频访问的表(热数据)放置在映射到 NVMe SSD 的表空间,而将历史归档表(冷数据)放置在映射到机械硬盘(HDD)的表空间,从而最大化硬件利用率。
容量管理 : 当某个磁盘分区空间不足时,可以通过创建指向新分区的表空间来扩展存储容量,而无需迁移整个数据库。
2. 内置表空间详解
openGauss 初始化后,会自动创建两个关键的系统表空间:
pg_default: 默认表空间。对应物理路径$GAUSSDATA/base。如果用户在创建数据库或表时未指定表空间,数据将默认存储于此。
pg_global: 全局表空间。对应物理路径$GAUSSDATA/global。专门用于存储系统全局字典表(如pg_database,pg_authid等),这些表在整个集群的所有数据库中共享。
3. 表空间管理DDL
创建表空间
创建表空间前,必须确保物理目录已存在,且操作系统用户(通常是 omm)拥有读写权限。
sql
-- 示例:为高性能交易数据创建一个基于 SSD 的表空间
-- 假设物理路径为 /ssd_data/trading_sys
CREATE TABLESPACE ts_high_perf LOCATION '/ssd_data/trading_sys';
-- 示例:创建一个归档用的表空间,并指定所有者为 audit_user
CREATE TABLESPACE ts_archive OWNER audit_user LOCATION '/hdd_data/archive_year_2023';
查询表空间
sql
-- 方法一:使用 gsql 元命令查看(简洁视图)
\db
-- 方法二:查询系统视图 pg_tablespace(详细视图)
-- spcname: 名称, spcowner: 所有者OID, spclocation: 物理路径
SELECT spcname, spcowner, spclocation FROM pg_tablespace;
修改与删除
sql
-- 修改表空间名称
ALTER TABLESPACE ts_high_perf RENAME TO ts_ssd_trade;
-- 修改表空间所有者
ALTER TABLESPACE ts_archive OWNER TO db_admin;
-- 删除表空间(注意:表空间必须为空,不能包含任何数据库对象)
DROP TABLESPACE ts_archive;
二、Database数据库
数据库 (Database) 是数据库对象的集合。在 openGauss 中,实现了强隔离机制:
1.访问隔离 : 连接到数据库
A的会话无法直接查询数据库B中的表。2.物理分布 : 一个数据库中的对象可以分布在多个表空间中;反之,一个表空间也可以存储多个数据库的数据。
数据库管理DDL
创建数据库
创建数据库时,可以配置其默认表空间、字符集编码以及连接限制。
sql
-- 基础创建
CREATE DATABASE crm_system;
-- 高级创建:指定所有者、字符集、编码及默认表空间
CREATE DATABASE fin_reporting
OWNER fin_admin
ENCODING 'UTF8'
LC_COLLATE 'en_US.UTF-8'
LC_CTYPE 'en_US.UTF-8'
TABLESPACE ts_ssd_trade
CONNECTION LIMIT 50;
查询数据库信息
sql
-- 方法一:元命令查看(\l+ 可以显示大小和描述)
\l+
-- 方法二:查询 pg_database 系统表
SELECT datname, datdba, encoding, datcollate, datctype FROM pg_database;
修改与维护
sql
-- 修改数据库默认表空间(会将库中默认表空间下的所有表移动到新位置,耗时操作)
ALTER DATABASE crm_system SET TABLESPACE ts_archive;
-- 重命名数据库
ALTER DATABASE crm_system RENAME TO crm_prod;
-- 删除数据库(危险操作!且当前不能有活跃连接)
DROP DATABASE fin_reporting;
三、Datafile Segment数据文件段
在操作系统层面,数据库表并不是无限增长的单一文件。openGauss 采用了分段存储策略。

1. 物理存储路径规则
假设数据库 OID 为 16384,表 OID 为 24576:
默认表空间 : 文件位于 $GAUSSDATA/base/16384/24576。
自定义表空间 : 文件位于 <tablespace_path>/PG_9.2_201611171/16384/24576(路径包含版本号目录)。
2. 1GB 切分机制
为了兼容不同文件系统的限制并优化备份恢复效率,当单张表的数据量超过 1GB 时,openGauss 会自动将其切分。
第一个文件:
24576第二个文件:
24576.1第三个文件:
24576.2以此类推...
这种机制对用户是透明的,用户只需像操作普通表一样进行读写。
四、Block数据块
Block(也称为 Page)是数据库内核进行磁盘 I/O 和内存缓存管理的基本单位。
1. 为什么是 8KB?
openGauss 的默认块大小为 8KB。
读写原理 : 即使 SQL 语句只查询了一行数据(例如 100 字节),数据库也会从磁盘读取包含该行的整个 8KB 数据块到内存(Shared Buffer)中。
写放大: 修改一行数据,最终落盘时也是重写整个 8KB 块(通过 WAL 和 Checkpoint 机制)。
2. 验证块大小
由于 block_size 是在数据库初始化(gs_initdb)阶段确定的不可变参数,我们只能查询确认。
sql
-- 查询当前实例的块大小设置
SELECT name, setting, unit, context
FROM pg_settings
WHERE name = 'block_size';
输出示例 : setting 为 8192,context 为 internal(表示仅内部只读)。
五、练习题
1.编写 SQL 语句,创建一个名为 ts_nvme_fast 的表空间,其对应的物理文件系统路径为 /dev/nvme0n1/pg_data。
2.创建一个名为 e_commerce_db 的数据库,要求字符集为 UTF8,并将其默认表空间指定为上题创建的 ts_nvme_fast。
3.编写 SQL 查询语句,从 pg_tablespace 系统表中查找所有者为 omm 用户的表空间名称 (spcname)。
4.将表空间 ts_nvme_fast 的名称修改为 ts_hot_data。
5.编写 SQL 语句,删除名为 ts_hot_data 的表空间。
6.修改数据库 e_commerce_db 的配置,将其允许的最大并发连接数限制为 100。
7. 简述 openGauss 中 pg_default 表空间的作用及其对应的默认物理路径变量。
8.当一张表的物理大小增长到 2.5GB 时,该表在磁盘上会由几个文件段组成?请写出它们的文件名模式(假设表 OID 为 12345)
9.编写 SQL 语句,将数据库 e_commerce_db 重命名为 online_shop_v2。
10.openGauss 进行磁盘 I/O 操作的最小单位是什么?默认大小是多少字节?
11.编写 SQL 语句,查询当前数据库实例的默认块大小 (block_size),并显示其单位。
12.判断题:在 openGauss 中,用户连接到数据库 A 后,可以使用 SELECT * FROM B.public.table1 直接查询数据库 B 中的表。(True/False)
13.编写 SQL 语句,将数据库 online_shop_v2 的所有者修改为用户 shop_admin。
14.在 gsql 命令行工具中,哪个元命令可以显示所有数据库的详细列表(包括大小、表空间、描述等)?
15.如果一个表空间中仍然存储着一张表的数据,直接执行 DROP TABLESPACE 会发生什么?
六、答案与解析
1.
sql
CREATE TABLESPACE ts_nvme_fast LOCATION '/dev/nvme0n1/pg_data';
解析 : 创建表空间使用
CREATE TABLESPACE语句,并且必须使用LOCATION子句指定一个已存在且权限正确的物理目录绝对路径。
2.
sql
CREATE DATABASE e_commerce_db ENCODING 'UTF8' TABLESPACE ts_nvme_fast;
解析 : 在创建数据库时,使用
ENCODING参数指定字符集,使用TABLESPACE参数指定该数据库对象的默认存储位置。
3.
sql
SELECT spcname FROM pg_tablespace WHERE spcowner = (SELECT oid FROM pg_roles WHERE rolname = 'omm');
解析 :
pg_tablespace系统表中记录的是所有者的 OID (spcowner),而不是用户名。因此,需要通过子查询从pg_roles表中获取用户名对应的 OID 进行匹配。
4.
sql
ALTER TABLESPACE ts_nvme_fast RENAME TO ts_hot_data;
解析 : 修改表空间名称的标准语法是
ALTER TABLESPACE <old_name> RENAME TO <new_name>。
5.
sql
DROP TABLESPACE ts_hot_data;
解析 : 删除表空间使用
DROP TABLESPACE语句。前提是该表空间必须为空,不能包含任何数据库对象。
6.
sql
ALTER DATABASE e_commerce_db CONNECTION LIMIT 100;
解析 :
ALTER DATABASE语句可以修改数据库的多种属性,CONNECTION LIMIT子句用于设置该数据库允许的最大并发连接数。
7.
作用:存储未指定表空间的普通用户对象;物理路径:$GAUSSDATA/base。
解析 :
pg_default是系统初始化的默认表空间,对应数据目录下的base子目录。
8.
3个文件。文件名模式为:12345 (1GB), 12345.1 (1GB), 12345.2 (0.5GB)。
解析 : openGauss 采用分段存储机制,当单表数据文件超过 1GB 时会自动切分。主文件名为 OID,后续分段文件名为 OID 后加
.1,.2等后缀。
9.
sql
ALTER DATABASE e_commerce_db RENAME TO online_shop_v2;
解析 : 数据库重命名使用
ALTER DATABASE ... RENAME TO语法。注意,执行此操作时,当前用户不能连接在被重命名的数据库上。
10.
Block (数据块/页)。默认大小为 8KB (8192 字节)。
解析: Block 是数据库内核进行磁盘 I/O 和内存缓存管理的最小原子单位,默认大小在初始化时固定为 8KB。
11.
sql
SELECT setting, unit FROM pg_settings WHERE name = 'block_size';
解析 :
block_size是一个内部只读参数,无法通过配置文件修改,可以通过查询pg_settings视图来确认其当前值和单位。
12.
False
解析 : openGauss 采用了强隔离机制,不同的数据库之间是逻辑隔离的,不支持直接使用
database.schema.table的方式进行跨库查询。
13.
sql
ALTER DATABASE online_shop_v2 OWNER TO shop_admin;
解析 : 修改数据库(或其他对象)所有者的标准语法是
ALTER ... OWNER TO <new_owner>。
14.
\l+
解析 :
\l是列出数据库的基本信息,加上+号(即\l+)会显示扩展信息,包括数据库的大小、默认表空间和详细描述等。
15.
执行失败并报错。必须先删除该表空间内的所有对象(表、索引等),使其为空后才能删除。
解析 : 为了保障数据安全,openGauss 禁止删除非空的表空间。必须先将表空间内的对象删除 (
DROP) 或移动 (ALTER ... SET TABLESPACE) 到其他表空间。

日期:2025年12月24日
专栏:openGauss