PostgreSQL简介(二)—— Database Roles

本文介绍PostgreSQL中的角色管理,包括角色的创建、属性配置、权限分配及角色成员管理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、角色(Role)

PostgreSQL使用role这一概念来控制数据库的访问权限。一个role可以看作是一个数据的user,或者是一组数据库的user,取决于你如何设置role。Role可以作为数据库对象(for example, tables and functions)的拥有者,将这些数据库对象的权限分配给其他role来控制数据库对象的访问权限。

  • 管理Role
--- role表 ---
postgres=# \d pg_roles 
                         View "pg_catalog.pg_roles"
     Column     |           Type           | Collation | Nullable | Default 
----------------+--------------------------+-----------+----------+---------
 rolname        | name                     |           |          | 
 rolsuper       | boolean                  |           |          | 
 rolinherit     | boolean                  |           |          | 
 rolcreaterole  | boolean                  |           |          | 
 rolcreatedb    | boolean                  |           |          | 
 rolcanlogin    | boolean                  |           |          | 
 rolreplication | boolean                  |           |          | 
 rolconnlimit   | integer                  |           |          | 
 rolpassword    | text                     |           |          | 
 rolvaliduntil  | timestamp with time zone |           |          | 
 rolbypassrls   | boolean                  |           |          | 
 rolconfig      | text[]                   |           |          | 
 oid            | oid                      |           |          | 

--- 创建role ---
postgres=# create role myrole;
CREATE ROLE
postgres=# select rolname from pg_roles;
       rolname        
----------------------
 postgres
 pg_monitor
 pg_read_all_settings
 pg_read_all_stats
 pg_stat_scan_tables
 pg_signal_backend
 myrole
(7 rows)
--- 删除role ---
postgres=# drop role myrole;
DROP ROLE

如果直接在shell中创建或删除role,可以执行 createuser namedropuser name

为了启动数据库,数据库在安装完之后,会自动创建超级用户角色,默认情况下,这个操作用户角色与操作系统运行PostgreSQL的用户同名,通常,这个角色被命名为postgres,在创建其他角色之前,必须先连接这个角色。

  • Role Attributes

在定义Role时,可以为其指定额外的属性,这些属性决定了Role的操作权限和认证权限, 例如:

--- 只有设置了login属性的role可以用来登陆 ---
postgres=# create role myrole login;
CREATE ROLE
postgres=# select rolname, rolcanlogin from pg_roles;
       rolname        | rolcanlogin 
----------------------+-------------
 postgres             | t
 pg_monitor           | f
 pg_read_all_settings | f
 pg_read_all_stats    | f
 pg_stat_scan_tables  | f
 pg_signal_backend    | f
 myrole               | t
(7 rows)

Create user 等同于 create role … login;

--- superuser角色会绕过除了登陆之外的所有权限检查,也就是登陆之后就畅通无阻了 ---
postgres=# create role myrole login superuser;
CREATE ROLE
postgres=# select rolname, rolcanlogin, rolsuper from pg_roles where rolname = 'myrole';
 rolname | rolcanlogin | rolsuper 
---------+-------------+----------
 myrole  | t           | t
(1 row)
--- 创建除superuser之外的role必须要为其赋予创建database的权限 ---
postgres=# create role myrole createdb;
CREATE ROLE
postgres=# select rolname, rolcreatedb from pg_roles where rolname = 'myrole';
 rolname | rolcreatedb 
---------+-------------
 myrole  | t
(1 row)
--- 创建除superuser之外的role必须要为其赋予创建role的权限 ---
postgres=# create role myrole createdb createrole;
CREATE ROLE
postgres=# select rolname, rolcreatedb, rolcreaterole from pg_roles where rolname = 'myrole';
 rolname | rolcreatedb | rolcreaterole 
---------+-------------+---------------
 myrole  | t           | t
(1 row)

一个具备createrole属性的role可以修改和删除其他role,但是无法操作superuser

--- 创建除superuser之外的role必须要为其赋予流复制(initiate streaming replication)的权限 ---
postgres=# create role myrole replication login;
CREATE ROLE
postgres=# select rolname, rolcreatedb, rolcreaterole, rolreplication from pg_roles where rolname = 'myrole';;
 rolname | rolcreatedb | rolcreaterole | rolreplication 
---------+-------------+---------------+----------------
 myrole  | f           | f             | t
(1 row)

在授予replication权限的同时,必须连同login权限一同授予

--- 创建role时,为其指定密码 ---
postgres=# create role myrole password 'awesomePass';
CREATE ROLE
postgres=# select rolname, rolpassword from pg_roles where rolname = 'myrole';
 rolname | rolpassword 
---------+-------------
 myrole  | ********
(1 row)
  • User(Role with login)

具备login属性的role可以认为是PostgreSQL的User,可以使用该User登陆PostgreSQL。

--- 修改认证方式 ---
-bash-4.2$ pwd
/var/lib/pgsql/10/data
-bash-4.2$ vi pg_hba.conf 
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
# local   all             all                                     peer
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
host    all             all             192.168.0.0/16          password
--- 重启服务 ---
[root@node-db ~]# systemctl restart postgresql-10
--- 创建User ---
postgres=# create role role_1 login password '888888';
CREATE ROLE
--- 使用新User登陆 ---
postgres=# \q
-bash-4.2$ psql -U role_1
Password for user role_1: 
psql: FATAL:  database "role_1" does not exist
-bash-4.2$ psql -U role_1 postgres
Password for user role_1: 
psql (10.4)
Type "help" for help.
  • PostgreSQL默认的本地(local)登陆验证方式为peer ,peer方式需要映射操作系统用户,也就是每一个peer方式的PostgreSQL用户需要一个同名的操作系统用户
  • psql -U user 默认会登陆一个与user同名的数据库,如果数据库不存在就会提示 psql: FATAL: database "user" does not exist ,使用 psql -U user database 指定数据库名称
  • Group role(Role Membership)

为了方便权限管理,PostgreSQL的Role可以包含其他Role,上层Role称为Group,被包含的Role称之为Group的Membership。为了便于理解,可以将Group当作是一组权限集合,一旦Group被赋给某个Role,该Role就成为了Group的Membership,Group内的Membership可以使用Group所具备的权限。

--- 创建role_1和role_2两个角色,将role_1赋给role_2,role_2就是role_1的membership,role_1是group ---
db_1=# create role role_1 createdb ;
CREATE ROLE
db_1=# create role role_2;
CREATE ROLE
db_1=# grant role_1 to role_2 ;
GRANT ROLE
--- 创建role_3,将role_2赋给role_3,角色之间可以相互授权,但不能形成循环授权 ---
db_1=# grant role_2 to role_3;
GRANT ROLE
db_1=# grant role_3 to role_1;
ERROR:  role "role_3" is a member of role "role_1"

Membership有两种方式使用Group的权限:一种是切换到Group role,这样就将当前数据库操作的session变成了Group role,所有的操作都是以Group role身份进行,比如新创建的对象的owner就是Group role,类似Linux系统中的 su 操作;另一种是继承,通过设置角色的 inherit 属性,使Membership在被赋予Group时获得Group的权限,这样Membership就可以以自己的身份进行相应的操作。

--- 设置测试数据 ---
postgres=# create role role_1;
CREATE ROLE
postgres=# set role role_1;
SET
postgres=> create table table_1(a int primary key);
CREATE TABLE
postgres=> reset role;
RESET
postgres=# create role role_2;
CREATE ROLE
postgres=# set role role_2;
SET
postgres=> create table table_2(a int primary key);
CREATE TABLE
postgres=> reset role;
RESET
postgres=# select * from pg_tables where tablename like 'table%';
 schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity 
------------+-----------+------------+------------+------------+----------+-------------+-------------
 public     | table_1   | role_1     |            | t          | f        | f           | f
 public     | table_2   | role_2     |            | t          | f        | f           | f
(2 rows)
--- 通过继承来获得权限 ---
postgres=# create role role_3;
CREATE ROLE
postgres=# set role role_3;
SET
postgres=> select * from table_1;
ERROR:  permission denied for relation table_1
postgres=> select * from table_2;
ERROR:  permission denied for relation table_2
postgres=> reset role;
RESET
postgres=# grant role_1 to role_3;
GRANT ROLE
postgres=# set role role_3;
SET
postgres=> select * from table_1;
 a 
---
(0 rows)

postgres=> select * from table_2;
ERROR:  permission denied for relation table_2
--- 通过切换来获得权限 ---
postgres=> reset role;
RESET
postgres=# create role role_4 login password '888888' noinherit;
CREATE ROLE
postgres=# grant role_2 to role_4;
GRANT ROLE
postgres=# \q
-bash-4.2$ psql -U role_4 -d postgres
Password for user role_4: 
psql (10.4)
Type "help" for help.

postgres=> select * from table_2;
ERROR:  permission denied for relation table_2
postgres=> create table table_3(a int primary key);
CREATE TABLE
postgres=> set role role_1;
ERROR:  permission denied to set role "role_1"
postgres=> set role role_2;
SET
postgres=> select * from table_2;
 a 
---
(0 rows)
postgres=> create table table_4(a int primary key);
CREATE TABLE
postgres=> select * from pg_tables where tablename like 'table%';
 schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity 
------------+-----------+------------+------------+------------+----------+-------------+-------------
 public     | table_1   | role_1     |            | t          | f        | f           | f
 public     | table_2   | role_2     |            | t          | f        | f           | f
 public     | table_3   | role_4     |            | t          | f        | f           | f
 public     | table_4   | role_2     |            | t          | f        | f           | f
(4 rows)
--- 查看角色信息 ---
postgres=> \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 role_1    | Cannot login                                               | {}
 role_2    | Cannot login                                               | {}
 role_3    | Cannot login                                               | {role_1}
 role_4    | No inheritance                                             | {role_2}
  • LOGINSUPERUSERCREATEDBCREATEROLE 属于特殊权限,不能继承,但是依然可以切换Role后使用;
  • 删除Group或自动收回所有权限,但不会对Membership照成此外的任何影响;
  • 所有Role默认含有 inherit 属性,会自动继承Group的权限 ;
  • 删除Role

删除Role之前先删除与该role关联的其他对象,否则无法删除:

--- 无法直接删除非空角色 ---
postgres=# drop role role_1;
ERROR:  role "role_1" cannot be dropped because some objects depend on it
DETAIL:  owner of table table_1
--- 转移权限之后删除 ---
postgres=# drop role role_3;
DROP ROLE
postgres=# drop role role_4;
ERROR:  role "role_4" cannot be dropped because some objects depend on it
DETAIL:  owner of table table_3
postgres=# alter table table_3 owner to role_2;
ALTER TABLE
postgres=# drop role role_4;
DROP ROLE
--- 批量转移权限 ---
postgres=> reset role;
RESET
postgres=# select * from pg_tables where tablename like 'table%';
 schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity 
------------+-----------+------------+------------+------------+----------+-------------+-------------
 public     | table_1   | role_1     |            | t          | f        | f           | f
 public     | table_2   | role_2     |            | t          | f        | f           | f
 public     | table_3   | role_2     |            | t          | f        | f           | f
 public     | table_4   | role_2     |            | t          | f        | f           | f
(4 rows)

postgres=# reassign owned by role_2 to role_1;
REASSIGN OWNED
postgres=# select * from pg_tables where tablename like 'table%';
 schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity 
------------+-----------+------------+------------+------------+----------+-------------+-------------
 public     | table_1   | role_1     |            | t          | f        | f           | f
 public     | table_2   | role_1     |            | t          | f        | f           | f
 public     | table_3   | role_1     |            | t          | f        | f           | f
 public     | table_4   | role_1     |            | t          | f        | f           | f
(4 rows)
  • 系统内置Role

这里写图片描述

<think>嗯...用户明确要求了解PostgreSQL数据库迁移的具体方法和工具。根据用户最后的提问历史,这应该是ta首次询问数据库迁移相关内容,且特别强调需要指南或工具推荐。翻看系统提供的引用材料,发现信息相当完整:引用[1]是MySQL迁移指南,虽然不完全匹配但具有参考价值;引用[2]到[5]则精准覆盖了不同迁移场景的工具和流程。值得注意的是用户提到的"node-pg-migrate"和"pgcopydb"都是专业级工具,说明可能面临复杂业务场景。用户身份推测:可能是需要负责数据库迁移的运维工程师或后端开发者,提问方式显示ta对术语很熟悉。深层需求应该不止基础操作,可能包含迁移难点解决方案——比如如何减少停机时间、处理版本差异等。准备采用阶梯式回答结构:先概述迁移类型分类(逻辑迁移/物理迁移/滚动迁移),再分场景推荐工具。针对不同数据规模会给出具体参数建议,比如对100GB以上数据库必须使用pgcopydb这种物理迁移工具。还要补充关键细节:迁移后必须进行数据校验,这在新管理员容易忽略但引用[3]的导出表结构操作已隐含这点。特别注意事项:用户提供的引用[5]涉及大版本升级,这个异常重要——很多团队会卡在版本兼容问题。需要强调pg_upgrade命令的坑点:必须确保扩展版本匹配,否则迁移后可能出现静默错误。准备在回答最后特意提醒这点,并附解决方案链接。</think> 以下为PostgreSQL数据库迁移的完整指南,结合不同场景推荐专业工具和方法: ### 一、迁移方法分类 1. **逻辑迁移** - **适用场景**:跨大版本升级、跨平台迁移、结构变更 - **核心工具**: ```bash # 导出全库数据 pg_dumpall -U postgres -f full_backup.sql # 仅导出单库 pg_dump -U user dbname > dbname.sql ``` - **导入方法**: ```bash psql -U postgres -d newdb -f dbname.sql ``` **优点**:兼容性好,可筛选对象 **缺点**:大型数据库恢复时间长[^3] 2. **物理迁移** - **适用场景**:同版本迁移(如服务器硬件升级) - **操作流程**: ```bash # 停止数据库服务 systemctl stop postgresql # 复制数据目录 rsync -av /var/lib/postgresql/ /new_server/pgdata/ # 修改postgresql.conf中的data_directory ``` **注意**:需确保文件系统权限一致[^3] 3. **滚动迁移(最小停机时间)** ```mermaid graph LR A[主库运行] --> B[创建副本库] B --> C[应用层流量切换] C --> D[停主库追增量] ``` ### 、专业迁移工具推荐 1. **pgcopydb** - **特点**:并行复制、支持增量同步 ```bash pgcopydb clone --source "host=old dbname=prod" \ --target "host=new dbname=prod" ``` **优势**:TB级数据迁移效率提升50%+,支持断点续传[^4] 2. **pgloader** (支持从MySQL迁移) ```lisp LOAD DATABASE FROM mysql://user@old_host/dbname INTO postgresql://user@new_host/dbname; ``` **亮点**:自动转换数据类型,实时错误日志[^1] 3. **node-pg-migrate** - **适用场景**:CI/CD环境下的版本化管理 ```javascript // 创建迁移脚本 exports.up = (pgm) => { pgm.createTable('users', { id: 'id' }); }; ``` **优势**:迁移脚本版本控制,集成测试框架[^2] ### 三、关键操作步骤 1. **版本升级迁移**(使用pg_upgrade) ```bash pg_upgrade -b /old/bin -B /new/bin \ -d /old/data -D /new/data \ --link # 硬链接加速 ``` **注意**:先执行`pg_checksums`验证数据完整性[^5] 2. **迁移后验证** ```sql -- 数据校验 SELECT md5(t::text) FROM (TABLE old_table ORDER BY id) t EXCEPT SELECT md5(t::text) FROM (TABLE new_table ORDER BY id) t; ``` ### 四、迁移最佳实践 1. **业务低峰期操作**:避开交易高峰时段 2. **预迁移测试**:使用生产数据的1/10在测试环境验证 3. **监控指标**: - 迁移期间主库负载(CPU/IOPS) - 网络传输速率(建议≥1Gbps) - WAL日志堆积量 > **灾难恢复方案**:始终保留源数据库快照直至新库稳定运行72小时[^4] ### 常见问题解决方案 1. **编码冲突**:迁移前执行 `SET client_encoding = 'UTF8';` 2. **外键约束报错**:在导入脚本前添加 `SET session_replication_role = replica;` 3. **权限丢失**:使用`pg_dumpall --roles-only`备份角色[^3] **推荐迁移路径选择**: ``` 小规模/结构变更 → pg_dump MySQL迁移 → pgloader TB级/零停机 → pgcopydb 版本升级 → pg_upgrade 开发环境 → node-pg-migrate ``` **特别提示**:超过1TB的数据库建议采用物理迁移+逻辑校验的组合方案,可减少75%的停机时间[^4][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值