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

概述

在 KingbaseES 数据库中,表空间是数据库对象的物理存储位置,合理的表空间配置对数据库性能和管理至关重要。本文将深入探讨数据库和用户的默认表空间配置,并通过实战案例展示完整的配置流程。

一、数据库默认表空间

1.1 创建数据库时不指定表空间

复制代码
CREATE DATABASE shanjiatest1;

1.2 默认存放位置

表空间: sys_default

物理路径: <data>/base/数据库OID

1.3 查看数据库默认表空间

方法一:使用 \l+ 命令

复制代码
\l+ shanjiatest1

方法二:查询系统表

复制代码
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 查询结果分析

当前配置状态:

用户名: shanjiatestuser1

用户配置: 空(表示没有特殊配置)

默认表空间: 空(表示使用系统默认)

临时表空间: 空(表示使用系统默认)

详细解释:

默认表空间为空的意义

用户创建对象时使用数据库的默认表空间(sys_default)

等同于没有显式设置 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 查看关键系统参数

复制代码
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');

四、创建对象得默认行为

4.1 表在默认表空间的创建

复制代码
#不指定表空间创建表
CREATE TABLE shanjiatesttable1 (id SERIAL, name TEXT);

#验证表的表空间
SELECT
    c.relname as "表名",
    n.nspname as "模式名",
    a.rolname as "表所有者",
    CASE 
        WHEN c.reltablespace = 0 THEN 'sys_default(数据库默认表空间)'
        ELSE (SELECT spcname FROM sys_tablespace WHERE oid = c.reltablespace)
    END as "表空间",
    c.relfilenode as "文件节点号",
    sys_relation_filepath(c.oid) as "相对文件路径",
    (SELECT setting FROM sys_settings WHERE name = 'data_directory') || '/' || 
    sys_relation_filepath(c.oid) as "绝对文件路径",
    pg_size_pretty(pg_relation_size(c.oid)) as "表大小"
FROM sys_class c
JOIN sys_namespace n ON c.relnamespace = n.oid
JOIN sys_authid a ON c.relowner = a.oid
WHERE c.relname = 'shanjiatesttable1'
AND c.relkind = 'r';

4.2 索引在默认表空间的创建

复制代码
#不指定表空间创建索引
CREATE INDEX idx_my_table_name ON shanjiatesttable1(name);
#验证索引的表空间
SELECT 
    indexname as index_name,
    tablespace as tablespace_name
FROM sys_indexes 
WHERE indexname = 'idx_my_table_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 创建用户和表空间

复制代码
-- 1、创建用户
CREATE USER shanjiatest2 WITH PASSWORD '46eCN+hHit3Ggidr7u/A';
COMMENT ON ROLE shanjiatest2 IS 'shanjia测试用户';
GRANT USAGE ON SCHEMA public TO shanjiatest2;
-- 2、授权共享用户访问public
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO shanjiatest2;
GRANT ALL PRIVILEGES ON ALL PROCEDURES IN SCHEMA public TO shanjiatest2;
-- 3、创建表空间
CREATE TABLESPACE shanjiatest2_tbs OWNER shanjiatest2 
LOCATION '/home/kingbase/tablespaces/shanjiatest_tbs';
COMMENT ON TABLESPACE shanjiatest2_tbs IS '山佳应用专用表空间';
-- 4、授予表空间上的所有权限
GRANT ALL PRIVILEGES ON TABLESPACE shanjiatest2_tbs TO shanjiatest2;
-- 5、创建数据库并指定默认表空间
CREATE DATABASE shanjia WITH ENCODING 'UTF8' OWNER shanjiatest2 
TABLESPACE shanjiatest2_tbs ALLOW_CONNECTIONS TRUE;
COMMENT ON DATABASE shanjia IS 'shanjia测试数据库';
-- 6、创建Schema并授权以及设置search_path
\c shanjia
CREATE SCHEMA IF NOT EXISTS shanjia AUTHORIZATION shanjiatest2;
GRANT ALL PRIVILEGES ON SCHEMA shanjia TO shanjiatest2;
-- 设置整个数据库的默认search_path
ALTER DATABASE shanjia SET search_path TO shanjia, public;
-- 设置特定用户的search_path
ALTER ROLE shanjiatest2 SET search_path TO shanjia,public;
-- 7、授权public_to_user
GRANT USAGE ON SCHEMA public TO shanjiatest2;
-- 8、创建表
CREATE TABLE shanjia.shanjiatesttable2 (id SERIAL, name TEXT);
ALTER TABLE shanjia.shanjiatesttable2 OWNER TO shanjiatest2;
-- 9、创建索引
CREATE INDEX idx_my_table_name ON shanjia.shanjiatesttable2(name);
ALTER INDEX shanjia.idx_my_table_name OWNER TO shanjiatest2;

5.2 用户权限验证

复制代码
SELECT 
    rolname as "用户名",
    rolsuper as "超级用户",
    rolinherit as "继承权限",
    rolcreaterole as "可创建角色",
    rolcreatedb as "可创建数据库",
    rolcanlogin as "可登录",
    rolconnlimit as "连接限制",
    rolvaliduntil as "密码有效期",
    rolconfig as "角色配置",
    obj_description(oid, 'pg_authid') as "用户注释"
FROM sys_roles 
WHERE rolname = 'shanjiatest2';

5.3 表空间信息查询

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

5.4 数据库配置查询

复制代码
SELECT 
    datname as "数据库名",
    datdba::regrole as "拥有者",
    (SELECT spcname FROM sys_tablespace WHERE oid = dattablespace) as "默认表空间",
    datconnlimit as "连接限制",
    datacl as "访问权限列表",
    obj_description(oid, 'pg_database') as "数据库注释",
    encoding as "字符编码"
FROM sys_database 
WHERE datname = 'shanjia';

5.5 权限汇总报告

复制代码
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.6 PS:修改默认表空间配置

复制代码
--修改数据库的默认表空间
ALTER DATABASE mydb SET TABLESPACE new_tablespace;
-- 注意:这会移动现有对象到新表空间
--修改用户的默认表空间

-- 修改用户的默认表空间
ALTER USER myuser SET DEFAULT_TABLESPACE = new_tablespace;
-- 修改用户的临时表空间
ALTER USER myuser SET TEMPORARY_TABLESPACE = temp_tablespace;

5.7 综合验证脚本

复制代码
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 具有清晰的默认表空间继承机制,从系统参数到数据库再到用户层级。

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

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

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

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

相关推荐
X***C86244 分钟前
Redis开启远程连接
数据库·redis·缓存
v***91301 小时前
DVWA靶场通关——SQL Injection篇
数据库·sql
x***13391 小时前
如何在Linux中找到MySQL的安装目录
linux·运维·mysql
学c菜鸟鸟1 小时前
漏洞知识——sql注入(二)
数据库·sql·oracle
Y***89081 小时前
【JAVA进阶篇教学】第十二篇:Java中ReentrantReadWriteLock锁讲解
java·数据库·python
周杰伦fans1 小时前
在C#中,`StringContent` 是 `HttpContent` 的一个派生类
开发语言·数据库·c#
P***84391 小时前
SQL多行数据合并到一行中的一个字段
数据库·sql
j***29481 小时前
【MySQL】数据库和表的操作
数据库·mysql·oracle
梅梅绵绵冰2 小时前
ssm整合框架
数据库·mybatis