概述

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

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

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

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

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

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐