文档首页> 数据仓库服务 GaussDB(DWS)> 故障排除> 账号/权限/密码> 用户存在依赖关系无法删除如何处理
更新时间:2024-01-25 GMT+08:00

用户存在依赖关系无法删除如何处理

问题现象

数据库使用中遇到某些用户离职或者角色变更时,要对其账号进行销户、权限进行回收等操作,但是删除用户时出现类似role “u1” cannot be dropped because some objects depend on it的报错信息,无法删除该用户。

例如,要删除用户u1时,出现如下提示:

1
2
3
4
testdb=# DROP USER u1;
ERROR:  role "u1" cannot be dropped because some objects depend on it 
DETAIL:  owner of database testdb 
3 objects in database gaussdb

原因分析

如果用户或角色的权限比较复杂、依赖较多,删除用户时就会报错存在依赖关系无法删除。通过上述问题现象中的ERROR的提示信息,获取以下信息:

  • 要删除的用户为数据库testdb的owner。
  • 有3个依赖的对象在gaussdb数据库中。

处理方法

  • 要删除的用户为一个数据库的owner,需要将对象的所有权重新分配给其他用户。有以下两种处理方法:
    方式一:将数据库owner转移给其他用户。例如,使用ALTER语句将数据库testdb的owner用户u1修改为u2。
    1
    2
    3
    4
    5
    6
    7
    8
    testdb=# ALTER DATABASE testdb OWNER to u2;
    ALTER DATABASE
    testdb=# \l 
                                       List of databases    
       Name    |   Owner  | Encoding |   Collate   |    Ctype    |    Access privileges 
    -----------+----------+----------+-------------+-------------+------------------------- 
     testdb    | u2       | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
    (4 rows) 
    
    执行删除u1用户的命令,不再提示“owner of database testdb”的信息。
    1
    2
    3
    testdb=# DROP USER u1;
    ERROR:  role "u1" cannot be dropped because some objects depend on it 
    DETAIL:  3 objects in database gaussdb
    
    方式二:如果已确认不需要数据库testdb,也可直接将其删除。将所有u1拥有的数据库对象的属主更改为u2。
    1
    2
    testdb=# REASSIGN OWNED BY u1 TO u2;
    REASSIGN OWNED
    

    清理owner是u1的对象。请谨慎使用,会将用户同名的schema也一同清理掉。

    1
    2
    testdb=# DROP OWNED by u1;
    DROP OWNED
    
  • 要删除的用户存在依赖关系,需要解除依赖关系。处理方法如下:
    1. 识别依赖关系。根据报错信息“3 objects in database gaussdb”可知gaussdb数据库里有3个对象依赖u1。由于库内系统表的依赖,在其他数据库中不会打印出详细的依赖对象信息,那么在gaussdb库中执行DROP USER的时候,会打印出具体的信息。

      连接到gaussdb库执行如下:

      1
      2
      3
      4
      gaussdb=# DROP USER u1;
      ERROR:  role "u1" cannot be dropped because some objects depend on it
      DETAIL:  privileges for table pg_class
      privileges for schema u2
      

      获取到依赖项的详细信息如下:

      1. privileges for table pg_class:pg_class上u1用户的权限。
      2. schema u2上u1用户的权限。
    2. 撤销依赖对象的权限。
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      gaussdb=# SELECT relname,relacl FROM pg_class WHERE relname = 'pg_class';
       relname  |              relacl
      ----------+----------------------------------
       pg_class | {=r/Ruby,u1=r/Ruby}
      (1 row)
      
      gaussdb=#SELECT nspname,nspacl FROM pg_namespace WHERE nspname = 'u2';
       nspname |           nspacl
      ---------+-----------------------------
       u2      | {u2=UC/u2,u2=LP/u2,u1=U/u2}
      
      gaussdb=# REVOKE SELECT ON TABLE pg_class FROM u1;
      REVOKE
      gaussdb=# REVOKE USAGE ON SCHEMA u2 FROM u1;
      REVOKE
      
    3. 再删除用户,可成功删除,不再提示有依赖。
      1
      2
      gaussdb=# DROP USER u1;
      DROP USER
      
  • 有场景中存在不知道要删除用户的具体依赖对象,还是不能成功删除,要如何处理呢?此处以构造的案例进行演示,新建用户u3, 并赋予u2的SELECT权限。
    1
    2
    3
    testdb2=# DROP USER u3;
    ERROR:  role "u3" cannot be dropped because some objects depend on it
    DETAIL:  2 objects in database gaussdb
    
    1. pg_shdepend系统表里记录了各个有依赖的对象的oid及其依赖关系。首先获取到用户的oid,再去系统表中找对应的依赖记录。
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      testdb2=# SELECT oid ,rolname FROM pg_roles WHERE rolname = 'u3';
          oid     | rolname
      ------------+---------
       2147484573 | u3
      (1 row)
      
      gaussdb=# SELECT * FROM pg_shdepend WHERE refobjid = 2147484573;
       dbid  | classid |   objid    | objsubid | refclassid |  refobjid  | deptype | objfile
      -------+---------+------------+----------+------------+------------+---------+---------
       16073 |    2615 | 2147484575 |        0 |       1260 | 2147484573 | o       |
       16073 |    2615 | 2147484025 |        0 |       1260 | 2147484573 | a       |
      (2 rows)
      

      由于dependType不同,因此有两条记录,一条记录代表权限依赖(a),另一条记录代表自身是一个对象的owner。

    2. 获取到的classid,代表依赖当前用户的对象的记录表的oid,在pg_class表中找到对应依赖即可。
      1
      2
      3
      4
      5
      gaussdb=# SELECT relname,relacl FROM pg_class WHERE oid = 2615;
         relname    |     relacl
      --------------+----------------
       pg_namespace | {=r/role23}
      (1 row)
      
    3. 通过查询记录表是pg_namespace,那么就可以确认依赖用户的是一个schema。再到pg_namespace系统表中,查询1获取到的objid,可确认具体对象。
      1
      2
      3
      4
      5
      6
      gaussdb=# SELECT nspname,nspacl FROM pg_namespace WHERE oid in (2147484575,2147484025);
       nspname |                         nspacl
      ---------+---------------------------------------------------------
       u3      |
       u2      | {u2=UC/u2,u2=LP/u2,u3=U/u2}
      (2 rows)
      

      这里看到有两个schema,u3是用户同名的schema,u2是赋权的schema,撤销赋权schema权限。

      1
      2
      gaussdb=# REVOKE USAGE ON SCHEMA u2 FROM u3;
      REVOKE
      
    4. 再删除用户u3,可成功删除。
      1
      2
      gaussdb=# DROP USER u3;
      DROP USER