PostgreSQL教程FG025-PG模式(Schema):创建与权限管理
本文档详细介绍PostgreSQL模式(Schema)的概念、创建、管理和权限控制,风哥教程参考PostgreSQL官方文档内容,适合数据库管理员和开发人员在生产环境中使用模式进行数据库对象的组织和权限管理。
Part01-基础概念与理论知识
1.1 PostgreSQL模式概念
模式是数据库中的一个命名空间,用于组织数据库对象(如表、视图、函数等)。模式可以理解为数据库中的文件夹,用于将数据库对象分类存放。更多视频教程www.fgedu.net.cn
- 组织数据库对象,提高管理效率
- 实现多租户架构
- 隔离不同应用或模块的数据库对象
- 控制权限,实现更精细的访问控制
1.2 PostgreSQL模式的优势
— 1. 命名空间隔离
— 不同模式中可以有同名的表
CREATE SCHEMA schema1;
CREATE SCHEMA schema2;
CREATE TABLE schema1.users (id SERIAL PRIMARY KEY, name VARCHAR(50));
CREATE TABLE schema2.users (id SERIAL PRIMARY KEY, name VARCHAR(50), email VARCHAR(100));
— 2. 权限管理
— 可以为不同模式设置不同的权限
GRANT ALL ON SCHEMA schema1 TO user1;
GRANT SELECT ON SCHEMA schema2 TO user2;
— 3. 组织管理
— 按功能或应用模块组织数据库对象
CREATE SCHEMA sales;
CREATE SCHEMA inventory;
CREATE SCHEMA hr;
— 4. 多租户支持
— 为每个租户创建独立的模式
CREATE SCHEMA tenant1;
CREATE SCHEMA tenant2;
CREATE SCHEMA tenant3;
1.3 PostgreSQL模式层级结构
PostgreSQL的数据库对象层级结构:
- 数据库(Database):最高层级,包含多个模式
- 模式(Schema):中间层级,包含多个数据库对象
- 数据库对象(Object):最低层级,如表、视图、函数等
Part02-生产环境规划与建议
2.1 模式设计原则
— 1. 按功能模块划分
— 示例:电商系统
CREATE SCHEMA sales; — 销售相关
CREATE SCHEMA inventory; — 库存相关
CREATE SCHEMA logistics; — 物流相关
CREATE SCHEMA finance; — 财务相关
CREATE SCHEMA user; — 用户相关
— 2. 按多租户划分
— 示例:SaaS应用
CREATE SCHEMA tenant_001;
CREATE SCHEMA tenant_002;
CREATE SCHEMA tenant_003;
— 3. 按环境划分
— 示例:开发、测试、生产
CREATE SCHEMA dev;
CREATE SCHEMA test;
CREATE SCHEMA prod;
— 4. 按数据类型划分
— 示例:主数据、业务数据、日志数据
CREATE SCHEMA master_data;
CREATE SCHEMA business_data;
CREATE SCHEMA logs;
2.2 模式命名规范
模式命名规范:
- 使用小写字母:避免大小写敏感问题
- 使用下划线分隔:提高可读性
- 简洁明了:反映模式的用途
- 避免保留字:不要使用PostgreSQL保留字
- 统一前缀:对于多租户场景,使用统一前缀
2.3 模式权限模型
— 1. 模式权限类型
— – CREATE:在模式中创建对象的权限
— – USAGE:访问模式中对象的权限
— 2. 默认权限
— – 超级用户拥有所有模式的所有权限
— – 模式所有者拥有该模式的所有权限
— – 其他用户需要显式授予权限
— 3. 权限继承
— 模式权限不会自动继承,需要显式授予
— 4. 权限管理策略
— – 最小权限原则:只授予必要的权限
— – 角色管理:使用角色管理权限
— – 定期审计:定期检查和更新权限
Part03-生产环境项目实施方案
3.1 模式创建与管理
3.1.1 创建模式
— 1. 创建基本模式
CREATE SCHEMA sales;
— 2. 创建模式并指定所有者
CREATE SCHEMA sales OWNER fgedu;
— 3. 创建模式(如果不存在)
CREATE SCHEMA IF NOT EXISTS sales;
— 4. 创建模式并授权
CREATE SCHEMA sales;
GRANT ALL ON SCHEMA sales TO fgedu;
3.1.2 查看模式
— 1. 查看所有模式
\dn
— 2. 查看模式详情
\dn+ sales
— 3. 使用SQL查询查看模式
SELECT schema_name, schema_owner
FROM information_schema.schemata
WHERE schema_name NOT LIKE ‘pg_%’ AND schema_name != ‘information_schema’;
— 4. 查看模式中的对象
\dt sales.*
\dv sales.*
\df sales.*
3.1.3 修改模式
— 1. 修改模式所有者
ALTER SCHEMA sales OWNER TO fgedu;
— 2. 重命名模式
ALTER SCHEMA sales RENAME TO sales_schema;
3.1.4 删除模式
— 1. 删除空模式
DROP SCHEMA sales;
— 2. 删除模式及其所有对象
DROP SCHEMA sales CASCADE;
— 3. 删除模式(如果存在)
DROP SCHEMA IF EXISTS sales CASCADE;
3.2 模式权限管理
3.2.1 授予模式权限
— 1. 授予CREATE权限
GRANT CREATE ON SCHEMA sales TO fgedu;
— 2. 授予USAGE权限
GRANT USAGE ON SCHEMA sales TO fgedu;
— 3. 授予所有权限
GRANT ALL ON SCHEMA sales TO fgedu;
— 4. 授予权限给角色
CREATE ROLE sales_role;
GRANT CREATE, USAGE ON SCHEMA sales TO sales_role;
GRANT sales_role TO fgedu;
3.2.2 撤销模式权限
— 1. 撤销CREATE权限
REVOKE CREATE ON SCHEMA sales FROM fgedu;
— 2. 撤销USAGE权限
REVOKE USAGE ON SCHEMA sales FROM fgedu;
— 3. 撤销所有权限
REVOKE ALL ON SCHEMA sales FROM fgedu;
3.2.3 查看模式权限
— 1. 查看模式权限
SELECT grantee, privilege_type
FROM information_schema.schema_privileges
WHERE schema_name = ‘sales’;
— 2. 查看用户的模式权限
SELECT schema_name, privilege_type
FROM information_schema.schema_privileges
WHERE grantee = ‘fgedu’;
3.3 模式搜索路径配置
3.3.1 查看当前搜索路径
— 1. 使用psql命令
\show search_path
— 2. 使用SQL查询
SHOW search_path;
— 结果:”$user”, public
— 3. 解释搜索路径
— $user:与当前用户名同名的模式
— public:默认模式
3.3.2 修改搜索路径
— 1. 临时修改(当前会话)
SET search_path TO sales, inventory, public;
— 2. 永久修改(用户级别)
ALTER USER fgedu SET search_path TO sales, inventory, public;
— 3. 永久修改(数据库级别)
ALTER DATABASE fgedudb SET search_path TO sales, inventory, public;
— 4. 验证修改
SHOW search_path;
Part04-生产案例与实战讲解
4.1 多租户架构案例
— 1. 创建租户模式
CREATE SCHEMA tenant_001;
CREATE SCHEMA tenant_002;
CREATE SCHEMA tenant_003;
— 2. 为每个租户创建相同结构的表
CREATE TABLE tenant_001.users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL
);
CREATE TABLE tenant_002.users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL
);
CREATE TABLE tenant_003.users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL
);
— 3. 创建租户角色并授权
CREATE ROLE tenant_001_role;
CREATE ROLE tenant_002_role;
CREATE ROLE tenant_003_role;
GRANT USAGE ON SCHEMA tenant_001 TO tenant_001_role;
GRANT ALL ON ALL TABLES IN SCHEMA tenant_001 TO tenant_001_role;
GRANT USAGE ON SCHEMA tenant_002 TO tenant_002_role;
GRANT ALL ON ALL TABLES IN SCHEMA tenant_002 TO tenant_002_role;
GRANT USAGE ON SCHEMA tenant_003 TO tenant_003_role;
GRANT ALL ON ALL TABLES IN SCHEMA tenant_003 TO tenant_003_role;
— 4. 创建租户用户并分配角色
CREATE USER tenant_001_user WITH PASSWORD ‘Tenant001@2026’;
CREATE USER tenant_002_user WITH PASSWORD ‘Tenant002@2026’;
CREATE USER tenant_003_user WITH PASSWORD ‘Tenant003@2026’;
GRANT tenant_001_role TO tenant_001_user;
GRANT tenant_002_role TO tenant_002_user;
GRANT tenant_003_role TO tenant_003_user;
— 5. 测试租户访问
— 以tenant_001_user身份登录
SET ROLE tenant_001_user;
— 只能访问自己的模式
SELECT * FROM tenant_001.users; — 成功
SELECT * FROM tenant_002.users; — 失败:权限被拒绝
— 重置角色
RESET ROLE;
4.2 应用模块分离案例
— 1. 创建应用模块模式
CREATE SCHEMA auth; — 认证模块
CREATE SCHEMA user; — 用户模块
CREATE SCHEMA product; — 产品模块
CREATE SCHEMA order; — 订单模块
CREATE SCHEMA payment; — 支付模块
— 2. 创建各模块的表
— 认证模块
CREATE TABLE auth.sessions (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
token VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL
);
— 用户模块
CREATE TABLE user.profiles (
id SERIAL PRIMARY KEY,
user_id INTEGER UNIQUE NOT NULL,
full_name VARCHAR(100) NOT NULL,
avatar VARCHAR(255),
bio TEXT
);
— 产品模块
CREATE TABLE product.categories (
id SERIAL PRIMARY KEY,
name VARCHAR(50) UNIQUE NOT NULL,
description TEXT
);
CREATE TABLE product.items (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
category_id INTEGER REFERENCES product.categories(id),
price DECIMAL(10,2) NOT NULL,
stock INTEGER NOT NULL
);
— 订单模块
CREATE TABLE order.orders (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
total_amount DECIMAL(10,2) NOT NULL,
status VARCHAR(20) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE order.order_items (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES order.orders(id),
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL,
price DECIMAL(10,2) NOT NULL
);
— 支付模块
CREATE TABLE payment.transactions (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES order.orders(id),
amount DECIMAL(10,2) NOT NULL,
payment_method VARCHAR(50) NOT NULL,
status VARCHAR(20) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
— 3. 创建模块角色并授权
CREATE ROLE auth_role;
CREATE ROLE user_role;
CREATE ROLE product_role;
CREATE ROLE order_role;
CREATE ROLE payment_role;
GRANT ALL ON SCHEMA auth TO auth_role;
GRANT ALL ON ALL TABLES IN SCHEMA auth TO auth_role;
GRANT ALL ON SCHEMA user TO user_role;
GRANT ALL ON ALL TABLES IN SCHEMA user TO user_role;
GRANT ALL ON SCHEMA product TO product_role;
GRANT ALL ON ALL TABLES IN SCHEMA product TO product_role;
GRANT ALL ON SCHEMA order TO order_role;
GRANT ALL ON ALL TABLES IN SCHEMA order TO order_role;
GRANT ALL ON SCHEMA payment TO payment_role;
GRANT ALL ON ALL TABLES IN SCHEMA payment TO payment_role;
— 4. 创建应用用户并分配角色
CREATE USER fgapp_user WITH PASSWORD ‘AppUser@2026’;
GRANT auth_role, user_role, product_role, order_role, payment_role TO fgapp_user;
— 5. 测试模块访问
SET ROLE fgapp_user;
— 访问各模块的表
SELECT * FROM auth.sessions;
SELECT * FROM user.profiles;
SELECT * FROM product.items;
SELECT * FROM order.orders;
SELECT * FROM payment.transactions;
— 重置角色
RESET ROLE;
4.3 权限隔离案例
— 1. 创建不同权限级别的模式
CREATE SCHEMA public_data; — 公开数据
CREATE SCHEMA internal_data; — 内部数据
CREATE SCHEMA admin_data; — 管理员数据
— 2. 创建各模式的表
CREATE TABLE public_data.products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL
);
CREATE TABLE internal_data.sales (
id SERIAL PRIMARY KEY,
product_id INTEGER REFERENCES public_data.products(id),
quantity INTEGER NOT NULL,
amount DECIMAL(10,2) NOT NULL,
sale_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE admin_data.users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
role VARCHAR(20) NOT NULL
);
— 3. 创建不同角色
CREATE ROLE public_role;
CREATE ROLE internal_role;
CREATE ROLE admin_role;
— 4. 授权
— 公开数据:所有人可访问
GRANT USAGE ON SCHEMA public_data TO public_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public_data TO public_role;
— 内部数据:内部用户可访问
GRANT USAGE ON SCHEMA internal_data TO internal_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA internal_data TO internal_role;
— 管理员数据:仅管理员可访问
GRANT USAGE ON SCHEMA admin_data TO admin_role;
GRANT ALL ON ALL TABLES IN SCHEMA admin_data TO admin_role;
— 5. 创建用户并分配角色
CREATE USER public_user WITH PASSWORD ‘PublicUser@2026’;
CREATE USER internal_user WITH PASSWORD ‘InternalUser@2026’;
CREATE USER admin_user WITH PASSWORD ‘AdminUser@2026’;
GRANT public_role TO public_user;
GRANT public_role, internal_role TO internal_user;
GRANT public_role, internal_role, admin_role TO admin_user;
— 6. 测试权限
— 以public_user身份登录
SET ROLE public_user;
SELECT * FROM public_data.products; — 成功
SELECT * FROM internal_data.sales; — 失败:权限被拒绝
SELECT * FROM admin_data.users; — 失败:权限被拒绝
— 以internal_user身份登录
SET ROLE internal_user;
SELECT * FROM public_data.products; — 成功
SELECT * FROM internal_data.sales; — 成功
SELECT * FROM admin_data.users; — 失败:权限被拒绝
— 以admin_user身份登录
SET ROLE admin_user;
SELECT * FROM public_data.products; — 成功
SELECT * FROM internal_data.sales; — 成功
SELECT * FROM admin_data.users; — 成功
— 重置角色
RESET ROLE;
Part05-风哥经验总结与分享
5.1 模式使用技巧
模式使用技巧:
- 合理规划模式:根据业务需求和数据结构规划模式
- 使用命名规范:制定统一的模式命名规范
- 配置搜索路径:合理配置模式搜索路径,简化SQL语句
- 使用角色管理权限:通过角色管理模式权限,提高管理效率
- 定期审计:定期检查模式权限,确保权限设置正确
- 备份考虑:备份时要考虑模式的完整性
- 性能优化:对于大型数据库,合理使用模式可以提高查询性能
- 版本管理:在开发环境中,使用模式隔离不同版本的代码
5.2 模式常见问题解决
— 1. 找不到对象
— 问题:执行SQL时提示找不到对象
— 解决:
— – 检查对象是否存在
— – 检查搜索路径是否包含对象所在的模式
— – 显式指定模式名,如 schema.table
— 2. 权限被拒绝
— 问题:访问模式或对象时提示权限被拒绝
— 解决:
— – 检查用户是否有模式的USAGE权限
— – 检查用户是否有对象的相应权限
— – 授予必要的权限
— 3. 搜索路径冲突
— 问题:搜索路径中存在同名对象
— 解决:
— – 调整搜索路径顺序
— – 显式指定模式名
— – 重命名对象
— 4. 模式所有者问题
— 问题:无法修改或删除模式
— 解决:
— – 确保以模式所有者身份操作
— – 或使用超级用户操作
— 5. 模式依赖问题
— 问题:删除模式时提示存在依赖对象
— 解决:
— – 使用CASCADE选项删除模式及其依赖对象
— – 先删除依赖对象,再删除模式
5.3 模式维护与管理
— 1. 定期检查模式权限
SELECT schema_name, grantee, privilege_type
FROM information_schema.schema_privileges
WHERE schema_name NOT LIKE ‘pg_%’ AND schema_name != ‘information_schema’;
— 2. 检查模式中的对象
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname NOT LIKE ‘pg_%’ AND schemaname != ‘information_schema’;
SELECT schemaname, viewname
FROM pg_views
WHERE schemaname NOT LIKE ‘pg_%’ AND schemaname != ‘information_schema’;
— 3. 优化模式搜索路径
— 为不同用户设置合适的搜索路径
ALTER USER fgedu SET search_path TO sales, inventory, public;
— 4. 清理未使用的模式
— 检查模式是否被使用
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name NOT LIKE ‘pg_%’ AND schema_name != ‘information_schema’
AND schema_name NOT IN (
SELECT DISTINCT schemaname
FROM pg_tables
UNION
SELECT DISTINCT schemaname
FROM pg_views
UNION
SELECT DISTINCT schemaname
FROM pg_proc
);
— 5. 模式备份
— 使用pg_dump备份特定模式
pg_dump -U fgedu -d fgedudb -n sales -f sales_schema.sql
— 6. 模式恢复
psql -U fgedu -d fgedudb -f sales_schema.sql
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
