KingbaseES 数据库与用户默认表空间深度解析与实战分享

在 KingbaseES 数据库中,表空间是用于存储数据库对象(如表、索引等)的物理位置,它实现了逻辑存储结构与物理文件路径的映射。合理的表空间规划对数据库的性能优化(如 I/O 负载均衡)、存储管理以及数据隔离至关重要。本文将深入解析 数据库 与 用户 这两个层面的默认表空间配置机制,并通过实战示例展示从创建到验证的完整操作流程。

一、数据库的默认表空间配置

1.1 默认创建行为

当使用 CREATE DATABASE 语句创建数据库且不显式指定表空间时,数据库将自动关联至系统默认表空间。

复制代码
CREATE DATABASE shanjiatest1;

说明:此操作未使用 TABLESPACE 子句,因此数据库会采用默认配置。

1.2 默认存储位置

逻辑表空间:sys_default(系统预设的默认表空间)。

物理路径:位于数据库集群的数据目录(data_directory)下的 base/数据库OID 子目录中。

数据库OID是系统为每个数据库分配的唯一对象标识符,可通过 sys_database 系统目录查询。

1.3 查看数据库的默认表空间

方法一:使用 KSQL 元命令(快捷方式)

复制代码
\l+ shanjiatest1

在输出结果中查找 Tablespace 字段,即可确认该数据库所属的表空间。当前默认表空间。

方法二:查询系统目录(详细信息)

language 复制代码
SELECT 
    datname AS database_name,
    dattablespace AS tablespace_oid,
    (SELECT spcname FROM sys_tablespace WHERE oid = dattablespace) AS tablespace_name,
    (SELECT setting FROM sys_settings WHERE name = 'data_directory') || '/base/' || oid AS physical_path
FROM sys_database 
WHERE datname = 'shanjiatest1';

输出示例:

二、用户的默认表空间配置

2.1 默认创建行为

创建用户时若不指定表空间,其默认表空间将与当前连接数据库的默认表空间保持一致。

复制代码
CREATE USER shanjiatestuser1 PASSWORD 'shanjiatestuser1';

执行示例:

2.2 关键配置项

默认表空间:决定了该用户创建数据库对象(如表、索引)时的存储位置。若未显式设置,将继承数据库的默认表空间(通常为 sys_default)。

临时表空间:用于存储临时对象(如排序、哈希生成的临时文件)。由系统参数 temp_tablespaces 决定,若该参数为空,则使用系统默认的临时文件位置。

2.3 查看用户的默认表空间配置

复制代码
SELECT 
    usename AS username,
    useconfig AS user_config,
    (SELECT setting FROM sys_settings WHERE name = 'default_tablespace') AS default_tablespace,
    (SELECT setting FROM sys_settings WHERE name = 'temp_tablespaces') AS temp_tablespaces
FROM sys_user 
WHERE usename = 'shanjiatestuser1';

输出示例:

2.4 查询结果分析(示例)

字段 含义解释
username shanjiatestuser1 用户名
user_config 用户级别的自定义配置参数(未设置)
default_tablespace 默认表空间参数为空,表示使用系统默认(即关联数据库的默认表空间,如 sys_default)
temp_tablespaces 临时表空间参数为空,表示使用系统默认的临时存储位置

"为空"并不代表没有表空间,而是指未进行个性化覆盖,实际行为将遵循更高层次的默认规则。

这种设计提供了灵活性:可以在系统级(default_tablespace 参数)、数据库级或用户级逐层定义和覆盖存储策略。

2.5 综合验证用户的实际默认表空间

为了清晰展示最终生效的默认表空间,可执行以下关联查询:

复制代码
SELECT 
    u.usename AS username,
    d.datname AS database_name,
    CASE 
        WHEN (SELECT setting FROM sys_settings WHERE name = 'default_tablespace') = '' 
        THEN 'sys_default'
        ELSE (SELECT setting FROM sys_settings WHERE name = 'default_tablespace')
    END AS user_default_tablespace,
    ts.spcname AS database_default_tablespace,
    (SELECT setting FROM sys_settings WHERE name = 'data_directory') || '/base/' || d.oid AS database_physical_path
FROM sys_user u, sys_database d, sys_tablespace ts
WHERE d.datname = current_database()
AND d.dattablespace = ts.oid
AND u.usename = 'shanjiatestuser1';

该查询将同时呈现用户关联的数据库、数据库的默认表空间及其物理存储路径,从而提供从用户到物理文件的完整映射视图。

输出示例:

三、系统参数的查询与管理

3.1 使用SQL检索关键的表空间关联参数

通过查阅 sys_settings 系统视图,用户可以精确地分析与表空间相关联的参数配置。

复制代码
SELECT 
    name as parameter_name,
    setting as current_value,
    short_desc as description
FROM sys_settings 
WHERE name IN ('default_tablespace', 'temp_tablespaces', 'data_directory');

此查询将返回以下核心参数的状态(结果示例):

default_tablespace :所有未显式指定表空间的对象(如表、索引)的默认存储位置。若值为空,将默认使用系统表空间 sys_default。
temp_tablespaces :用于指定排序、哈希等操作的临时表空间的列表。此参数也可为空,表示使用系统默认的临时文件路径。
data_directory:数据库集群的根数据目录,是计算对象物理绝对路径的基础

四、对象创建的默认表空间行为

当未指定表空间的情况下创建数据库对象时,其存储位置遵循一套默认的继承规则。了解此行为对于优化数据分布和磁盘I/O至关重要。

4.1 表创建的默认行为

场景:在不使用 TABLESPACE 子句的情况下创建表,表将自动存储到其所属数据库的默认表空间中。

复制代码
CREATE TABLE shanjiatesttable1 (id SERIAL, name TEXT);

验证:通过查询系统目录,可以确认表的存储逻辑、物理位置和大小,输出示例:

输出关键词:
表空间 :若显示 sys_default,则验证了对象存储于数据库默认表空间。
绝对文件路径:揭示了表在操作系统文件系统中的确切位置。

4.2 索引创建的默认行为

场景:默认情况下,索引会与其父表存储在同一表空间。此行为可以用 CREATE INDEX 子句显式覆盖。

复制代码
不指定表空间创建索引
CREATE INDEX idx_my_table_name ON shanjiatesttable1(name);
复制代码
SELECT 
    i.indexname as "索引名称",
    i.tablename as "所属表",
    'sys_default(数据库默认表空间)' as "表空间名称",
    '数据库默认表空间 (sys_default)' as "表空间说明",
    sys_relation_filepath(i.indexname::regclass) as "相对文件路径",
    (SELECT setting FROM sys_settings WHERE name = 'data_directory') || '/' || 
    sys_relation_filepath(i.indexname::regclass) as "完整物理路径",
    pg_size_pretty(pg_relation_size(i.indexname::regclass)) as "索引大小",
    i.indexdef as "索引定义"
FROM sys_indexes i
WHERE i.indexname = 'idx_my_table_name';

验证:查询索引信息,确认其位置与默认策略一致。

五、实战案例:构建一个完整的用户及表空间配置

本案例提供一个从用户、表空间到数据库及对象的完整配置流程,适用于生产环境下的独立应用数据隔离与权限管理规划。

5.1 创建用户、表空间及关联数据库的完整流程

该流程遵循"先认证后授权"的安全原则。

5.1.1. 创建用户,并使用注释进行标记

复制代码
CREATE USER shanjiatest2 WITH PASSWORD '46eCN+hHit3Ggidr7u/A';
COMMENT ON ROLE shanjiatest2 IS 'shanjia测试用户';

5.1.2. 授予该用户对Public模式的访问权

复制代码
GRANT USAGE ON SCHEMA public TO shanjiatest2;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO shanjiatest2;
GRANT ALL PRIVILEGES ON ALL PROCEDURES IN SCHEMA public TO shanjiatest2;

5.1.3. 创建专用表空间,并指定物理目录

复制代码
CREATE TABLESPACE shanjiatest2_tbs OWNER shanjiatest2 
LOCATION '/home/kingbase/tablespaces/shanjiatest_tbs';
COMMENT ON TABLESPACE shanjiatest2_tbs IS '山佳应用专用表空间';

5.1.4. 授予用户对该表空间的完全控制权限

复制代码
GRANT ALL PRIVILEGES ON TABLESPACE shanjiatest2_tbs TO shanjiatest2;

5.1.5. 创建数据库,明确指定使用新创建的表空间

复制代码
CREATE DATABASE shanjia WITH ENCODING 'UTF8' OWNER shanjiatest2 
TABLESPACE shanjiatest2_tbs ALLOW_CONNECTIONS TRUE;
COMMENT ON DATABASE shanjia IS 'shanjia测试数据库';

5.1.6. 切换至新数据库,创建专用模式并设置路径

复制代码
\c shanjia
CREATE SCHEMA IF NOT EXISTS shanjia AUTHORIZATION shanjiatest2;
GRANT ALL PRIVILEGES ON SCHEMA shanjia TO shanjiatest2;
-- 设置数据库和用户的默认搜索路径,优化对象解析效率
ALTER DATABASE shanjia SET search_path TO shanjia, public;
ALTER ROLE shanjiatest2 SET search_path TO shanjia,public;

5.1.7. 在新模式下创建测试表和索引

复制代码
CREATE TABLE shanjia.shanjiatesttable2 (id SERIAL, name TEXT);
ALTER TABLE shanjia.shanjiatesttable2 OWNER TO shanjiatest2;
CREATE INDEX idx_my_table_name ON shanjia.shanjiatesttable2(name);
ALTER INDEX shanjia.idx_my_table_name OWNER TO shanjiatest2;

完整的操作截图:

5.2 验证与审计

配置完成后,建议执行以下验证步骤,确保符合设计预期。

5.2.1 用户权限验证

复制代码
SELECT 
    rolname as "用户名",
    rolsuper as "超级用户",
    rolcanlogin as "可登录",
    rolconnlimit as "连接限制",
    obj_description(oid, 'pg_authid') as "用户注释"
FROM sys_roles 
WHERE rolname = 'shanjiatest2';

输出示例:

5.2.2 表空间信息查询

复制代码
SELECT 
    spcname as "表空间名",
    spcowner::regrole as "拥有者",
    obj_description(oid, 'pg_tablespace') as "表空间注释",
    sys_tablespace_location(oid) as "物理路径"
FROM sys_tablespace 
WHERE spcname = 'shanjiatest2_tbs';

输出示例:

5.2.3 数据库配置查询

复制代码
SELECT 
    datname as "数据库名",
    datdba::regrole as "拥有者",
    (SELECT spcname FROM sys_tablespace WHERE oid = dattablespace) as "默认表空间",
    encoding as "字符编码"
FROM sys_database 
WHERE datname = 'shanjia';

输出示例:

5.2.4 综合性权限审计报告

-- 检查用户对重点模式的具体权限

复制代码
WITH privilege_check AS (
    SELECT 
        nspname,
        'USAGE' as privilege_type,
        has_schema_privilege('shanjiatest2', oid, 'USAGE') as has_priv,
        has_schema_privilege('shanjiatest2', oid, 'USAGE WITH GRANT OPTION') as has_grant
    FROM sys_namespace 
    WHERE nspname IN ('shanjia', 'public')

    UNION ALL

    SELECT 
        nspname,
        'CREATE' as privilege_type,
        has_schema_privilege('shanjiatest2', oid, 'CREATE') as has_priv,
        has_schema_privilege('shanjiatest2', oid, 'CREATE WITH GRANT OPTION') as has_grant
    FROM sys_namespace 
    WHERE nspname IN ('shanjia', 'public')
)
SELECT 
    nspname as "模式名",
    privilege_type as "权限类型",
    CASE 
        WHEN has_priv THEN 'YES' 
        ELSE 'NO' 
    END as "是否有权限",
    CASE 
        WHEN has_grant THEN 'YES' 
        ELSE 'NO' 
    END as "是否可转授",
    CASE 
        WHEN has_priv AND has_grant THEN '完全权限(可转授)'
        WHEN has_priv THEN '基础权限'
        ELSE '无权限'
    END as "权限状态"
FROM privilege_check
ORDER BY nspname, privilege_type;

输出示例:

5.3 [附]后期配置调整

在应用生命周期中,可能需要调整资源的存储位置。

5.3.1 修改数据库的默认表空间(注意:此操作可能涉及大规模数据迁移)

复制代码
ALTER DATABASE shanjiadb SET TABLESPACE new_tablespace;

5.3.2 修改用户的默认表空间(仅影响此后创建的对象)

复制代码
ALTER USER myuser SET DEFAULT_TABLESPACE = new_tablespace;

5.3.3 修改用户的临时表空间

复制代码
ALTER USER myuser SET TEMPORARY_TABLESPACE = temp_tablespace;

5.4 综合验证脚本

复制代码
DO $$
DECLARE
    user_exists boolean;
    tablespace_exists boolean;
    database_exists boolean;
    schema_exists boolean;
    table_exists boolean;
    index_exists boolean;
    user_can_login boolean;
    table_owner_correct boolean;
    index_owner_correct boolean;
    user_has_tablespace_priv boolean;
    user_has_db_connect boolean;
    user_has_schema_usage boolean;
    user_has_table_select boolean;
BEGIN
    -- 检查用户
    SELECT EXISTS(SELECT 1 FROM sys_roles WHERE rolname = 'shanjiatest2') INTO user_exists;
    SELECT rolcanlogin FROM sys_roles WHERE rolname = 'shanjiatest2' INTO user_can_login;
    -- 检查表空间
    SELECT EXISTS(SELECT 1 FROM sys_tablespace WHERE spcname = 'earchives_tbs') INTO tablespace_exists;

    -- 检查表空间权限
    SELECT has_tablespace_privilege('shanjiatest2', 'earchives_tbs', 'CREATE') 
    INTO user_has_tablespace_priv;
    -- 检查数据库
    SELECT EXISTS(SELECT 1 FROM sys_database WHERE datname = 'shanjia') INTO database_exists;

    -- 检查数据库连接权限
    SELECT has_database_privilege('shanjiatest2', 'shanjia', 'CONNECT') 
    INTO user_has_db_connect;
    -- 检查schema
    SELECT EXISTS(SELECT 1 FROM sys_namespace WHERE nspname = 'shanjia') INTO schema_exists;

    -- 检查schema使用权限
    SELECT has_schema_privilege('shanjiatest2', 'shanjia', 'USAGE') 
    INTO user_has_schema_usage;
    -- 检查表
    SELECT EXISTS(SELECT 1 FROM sys_tables WHERE schemaname = 'shanjia' AND tablename = 'shanjiatesttable2') INTO table_exists;
    -- 检查表拥有者
    SELECT tableowner = 'shanjiatest2'
    FROM sys_tables
    WHERE schemaname = 'shanjia' AND tablename = 'shanjiatesttable2'
    INTO table_owner_correct;

    -- 检查表查询权限
    SELECT has_table_privilege('shanjiatest2', 'shanjia.shanjiatesttable2', 'SELECT') 
    INTO user_has_table_select;
    -- 检查索引(使用sys_class视图)
    SELECT EXISTS(
        SELECT 1 
        FROM sys_class c
        JOIN sys_namespace n ON c.relnamespace = n.oid
        WHERE c.relname = 'idx_my_table_name'
        AND n.nspname = 'shanjia'
        AND c.relkind = 'i'  -- 索引类型
    ) INTO index_exists;
    -- 检查索引拥有者
    SELECT EXISTS(
        SELECT 1 
        FROM sys_class c
        JOIN sys_roles r ON c.relowner = r.oid
        JOIN sys_namespace n ON c.relnamespace = n.oid
        WHERE c.relname = 'idx_my_table_name'
        AND n.nspname = 'shanjia'
        AND c.relkind = 'i'
        AND r.rolname = 'shanjiatest2'
    ) INTO index_owner_correct;
    RAISE NOTICE '=== KingbaseES 对象验证结果汇总 ===';
    RAISE NOTICE '用户创建: %', CASE WHEN user_exists THEN '✓ 成功' ELSE '✗ 失败' END;
    RAISE NOTICE '用户可登录: %', CASE WHEN user_can_login THEN '✓ 是' ELSE '✗ 否' END;
    RAISE NOTICE '表空间创建: %', CASE WHEN tablespace_exists THEN '✓ 成功' ELSE '✗ 失败' END;
    RAISE NOTICE '表空间权限: %', CASE WHEN user_has_tablespace_priv THEN '✓ 有CREATE权限' ELSE '✗ 无权限' END;
    RAISE NOTICE '数据库创建: %', CASE WHEN database_exists THEN '✓ 成功' ELSE '✗ 失败' END;
    RAISE NOTICE '数据库连接权限: %', CASE WHEN user_has_db_connect THEN '✓ 有权限' ELSE '✗ 无权限' END;
    RAISE NOTICE 'Schema创建: %', CASE WHEN schema_exists THEN '✓ 成功' ELSE '✗ 失败' END;
    RAISE NOTICE 'Schema使用权限: %', CASE WHEN user_has_schema_usage THEN '✓ 有权限' ELSE '✗ 无权限' END;
    RAISE NOTICE '表创建: %', CASE WHEN table_exists THEN '✓ 成功' ELSE '✗ 失败' END;
    RAISE NOTICE '表拥有者正确: %', CASE WHEN table_owner_correct THEN '✓ 是' ELSE '✗ 否' END;
    RAISE NOTICE '表查询权限: %', CASE WHEN user_has_table_select THEN '✓ 有权限' ELSE '✗ 无权限' END;
    RAISE NOTICE '索引创建: %', CASE WHEN index_exists THEN '✓ 成功' ELSE '✗ 失败' END;
    RAISE NOTICE '索引拥有者正确: %', CASE WHEN index_owner_correct THEN '✓ 是' ELSE '✗ 否' END;
    -- 综合评估
    RAISE NOTICE '=== 综合评估 ===';
    IF user_exists AND tablespace_exists AND database_exists AND schema_exists AND table_exists AND index_exists THEN
        RAISE NOTICE '基础对象创建: ✓ 全部成功';
    ELSE
        RAISE NOTICE '基础对象创建: ✗ 存在失败项';
    END IF;

    IF user_has_tablespace_priv AND user_has_db_connect AND user_has_schema_usage AND user_has_table_select THEN
        RAISE NOTICE '权限配置: ✓ 全部正确';
    ELSE
        RAISE NOTICE '权限配置: ✗ 存在权限问题';
    END IF;

    IF table_owner_correct AND index_owner_correct THEN
        RAISE NOTICE '对象所有权: ✓ 全部正确';
    ELSE
        RAISE NOTICE '对象所有权: ✗ 存在所有权问题';
    END IF;
END $$;

输出示例:

总结

通过本文的详细分析和实战案例,我们可以得出以下结论:

默认表空间机制:KingbaseES 具有清晰的默认表空间继承机制,从系统参数到数据库再到用户层级。

灵活配置:支持在数据库和用户级别分别设置默认表空间,满足不同应用场景需求。

完整权限体系:通过系统表查询可以全面了解表空间、权限和物理存储的关联关系。

最佳实践:建议为重要应用创建专用表空间,实现数据文件的物理隔离和管理优化。

合理的表空间规划和管理对于数据库性能、备份恢复和日常运维都具有重要意义,应根据实际业务需求制定相应的表空间策略。

相关推荐
萧曵 丶2 小时前
MongoDB 核心原理 + 高频面试题
数据库·mongodb
darling3312 小时前
mysql 自动备份以及远程传输脚本,异地备份
android·数据库·mysql·adb
Bruk.Liu2 小时前
(LangChain实战12):LangChain中的新型Chain之create_sql_query_chain
数据库·人工智能·sql·langchain
世界尽头与你2 小时前
MySQL InnoDB的 MVCC 实现机制
数据库·mysql
你刷碗2 小时前
基于S32K144 CESc生成随机数
android·java·数据库
松涛和鸣2 小时前
70、IMX6ULL LED驱动实战
linux·数据库·驱动开发·postgresql·sqlserver
世界尽头与你3 小时前
详解 MySQL 数据库索引实现机制 - B 树和 B + 树
数据库·mysql·索引
德彪稳坐倒骑驴3 小时前
MySQL Oracle面试题
数据库·mysql·oracle
数据知道3 小时前
PostgreSQL 核心原理:什么场景下开启 JIT 能提升性能?(JIT 编译)
数据库·postgresql