All Products
Search
Document Center

ApsaraDB RDS:Gagal menghapus akun di ApsaraDB RDS for PostgreSQL

Last Updated:Jun 21, 2026

Gejala

Saat menghapus akun dari instans ApsaraDB RDS for PostgreSQL, muncul error.

  • Saat menghapus akun melalui Konsol ApsaraDB RDS, muncul pesan error.

    • Pesan error menunjukkan bahwa objek database bergantung pada akun tersebut dan akun hanya dapat dihapus setelah dependensi tersebut dihilangkan.

    • Kode error: AccountActionForbidden.

  • Menjalankan pernyataan SQL untuk menghapus akun menghasilkan error berikut: ERROR: role "<username>" cannot be dropped because some objects depend on it

Penyebab

Penghapusan akun akan gagal jika akun tersebut menjadi dasar ketergantungan objek database pada instans RDS.

Contoh masalah

Misalnya, akun bernama user_to_be_dropped digunakan untuk membuat objek, seperti yang ditunjukkan dalam pernyataan SQL berikut:

  1. Gunakan akun istimewa untuk membuat database uji bernama testdb01.

    CREATE DATABASE testdb01;
  2. Gunakan akun istimewa untuk terhubung ke testdb01, buat akun uji bernama user_to_be_dropped, dan berikan izin yang diperlukan kepada akun uji tersebut.

    CREATE USER user_to_be_dropped WITH PASSWORD 'your_password' CREATEROLE CREATEDB;
    GRANT ALL ON SCHEMA public TO user_to_be_dropped;
    GRANT ALL ON DATABASE testdb01 TO user_to_be_dropped;
  3. Gunakan akun user_to_be_dropped untuk terhubung ke testdb01, lalu buat objek serta database uji bernama testdb02.

    CREATE SCHEMA test_nsp;
    CREATE TABLE test_nsp.test_tbl(a1 int);
    CREATE TABLE test_tbl(a2 int);
    CREATE DATABASE testdb02;
  4. Gunakan akun user_to_be_dropped untuk terhubung ke testdb02, buat objek, buat akun uji baru bernama user_to_be_dropped_2, dan berikan role akun baru tersebut kepada akun istimewa (testdbuser dalam contoh ini).

    CREATE SCHEMA testnsp;
    CREATE TABLE testnsp.tbl(a3 int);
    CREATE USER user_to_be_dropped_2 WITH PASSWORD 'your_password';
    GRANT user_to_be_dropped_2 TO testdbuser;

Saat mencoba menghapus akun user_to_be_dropped, operasi gagal karena terdapat objek dependen.

  • Gambar berikut menunjukkan pesan error yang muncul di Konsol ApsaraDB RDS.

    Pesan error-nya adalah "Database objects depend on the account for this operation. Please remove the dependencies and try again.", dan kode error-nya adalah AccountActionForbidden.

  • Pernyataan SQL:

    Catatan

    Pernyataan SQL contoh dijalankan untuk menghapus akun dari database default bernama postgres.

    DROP USER user_to_be_dropped;
    ERROR:  role "user_to_be_dropped" cannot be dropped because some objects depend on it
    DETAIL:  privileges for database testdb01
    owner of database testdb02
    privileges for membership of role testdbuser in role user_to_be_dropped_2
    4 objects in database testdb01
    2 objects in database testdb02
Penting

Akun istimewa awal tidak dapat dihapus.

Solusi

  • Pemrosesan batch. Metode ini bersifat coarse-grained, ringkas, dan efisien. Jika menjalankan pernyataan SQL untuk menghapus akun menghasilkan error, Anda dapat mentransfer objek milik akun tersebut ke akun lain secara batch sesuai petunjuk, lalu mencabut semua izin dari akun yang ingin dihapus.

  • Pemrosesan fine-grained. Setiap izin dan objek transparan serta dapat dikontrol. Anda dapat mengkueri objek yang bergantung pada akun yang ingin dihapus dan menghapus objek tersebut satu per satu.

Pemrosesan batch

  1. Konfirmasi objek dan izin milik akun yang ingin dihapus berdasarkan pesan error. Dalam contoh ini, contoh masalah digunakan.

    DROP USER user_to_be_dropped;
    ERROR:  role "user_to_be_dropped" cannot be dropped because some objects depend on it
    DETAIL:  privileges for database testdb01
    owner of database testdb02
    privileges for membership of role testdbuser in role user_to_be_dropped_2
    4 objects in database testdb01
    2 objects in database testdb02

    Pesan error tersebut mengonfirmasi bahwa akun target user_to_be_dropped memiliki objek dependen di database testdb01 dan testdb02. Secara spesifik:

    • Di database testdb01, akun memiliki hak akses pada empat objek.

    • Akun merupakan Pemilik database testdb02.

  2. Gunakan akun istimewa untuk login ke database yang disebutkan dalam pesan error, transfer objek milik akun yang ingin dihapus ke akun lain, lalu hapus izin atas objek tersebut dari akun yang ingin dihapus. Dalam contoh ini, akun testdbuser digunakan sebagai akun istimewa dan objek dialihkan ke akun tersebut.

    • Terhubung ke database testdb01 dan hapus objek yang dimiliki oleh akun user_to_be_dropped.

      DROP OWNED BY user_to_be_dropped;
    • Terhubung ke database testdb02, alihkan kepemilikan ke akun lain, lalu hapus objek yang dimiliki oleh akun user_to_be_dropped.

      -- Transfer kepemilikan database.
      REASSIGN OWNED BY user_to_be_dropped TO testdbuser;
      -- Hapus objek milik akun.
      DROP OWNED BY user_to_be_dropped;

Pemrosesan fine-grained

Langkah 1: Kueri objek dependen

Tabel sistem pg_shdepend mencatat dependensi objek database terhadap objek bersama, seperti role. Anda dapat mengkueri tabel ini untuk menemukan objek mana saja yang bergantung pada akun target. Misalnya, untuk menemukan objek yang bergantung pada akun user_to_be_dropped, lakukan langkah berikut:

  1. Gunakan akun istimewa untuk terhubung ke instans database dan kueri objek yang terkait dengan akun user_to_be_dropped.

    WITH role as (SELECT oid FROM pg_roles WHERE rolname = 'user_to_be_dropped')
    SELECT
        db.datname AS database,
        pg_class.relname AS classname,
        shp.objid AS oid,
        CASE
            WHEN shp.deptype = 'o' THEN 'Object Owner'
            WHEN shp.deptype = 'a' THEN 'In Access Control List'
            WHEN shp.deptype = 'r' THEN 'Policy Object'
        ELSE
            'CANNOT HAPPEN'  
        END
    FROM
        pg_shdepend shp
            LEFT JOIN pg_database db ON shp.dbid = db.oid
            JOIN pg_class ON shp.classid = pg_class.oid
    WHERE
        shp.refclassid = 1260 AND shp.refobjid IN (SELECT oid FROM role);

    Hasil berikut dikembalikan:

     database |    classname    |  oid  |          case
    ----------+-----------------+-------+------------------------
     testdb01 | pg_namespace    |  2200 | In Access Control List
              | pg_database     | 16399 | In Access Control List
     testdb01 | pg_namespace    | 16402 | Object Owner
     testdb01 | pg_class        | 16403 | Object Owner
     testdb01 | pg_class        | 16406 | Object Owner
              | pg_database     | 16409 | Object Owner
     testdb02 | pg_namespace    | 16410 | Object Owner
     testdb02 | pg_class        | 16411 | Object Owner
              | pg_auth_members | 16416 | In Access Control List

    Tabel berikut menjelaskan bidang-bidang dalam hasil tersebut.

    Bidang

    Deskripsi

    database

    Database tempat objek dependen berada. Jika bidang ini kosong, objek dependen merupakan objek global.

    classname

    Nama tabel sistem.

    oid

    Identifier objek (OID) dari objek dependen.

    case

    Jenis dependensi. Jenis dependensi umum berikut disediakan:

    • Owner: Akun yang ingin Anda hapus adalah pemilik objek tersebut.

    • ACL: Akun yang ingin Anda hapus ada dalam daftar kontrol akses (ACL).

  2. Untuk setiap oid yang dikembalikan pada langkah sebelumnya, gunakan akun istimewa untuk terhubung ke database yang sesuai dan kueri tabel sistem terkait untuk menemukan nama objeknya. Contohnya:

    • Dependensi objek global

      Nilai kosong pada bidang database menunjukkan dependensi terhadap objek global.

      • Untuk oid=16399, daftar kontrol akses dari testdb01 berisi entri untuk user_to_be_dropped.

        SELECT datname, datdba::regrole, datacl FROM pg_database WHERE oid = 16399;
         datname  |   datdba   |                                    datacl
        ----------+------------+------------------------------------------------------------------------------
         testdb01 | testdbuser | {=Tc/testdbuser,testdbuser=CTc/testdbuser,user_to_be_dropped=CTc/testdbuser}
        (1 row)
      • Untuk oid=16409, pemilik testdb02 adalah user_to_be_dropped.

        SELECT datname, datdba::regrole, datacl FROM pg_database WHERE oid = 16409;
         datname  |       datdba       | datacl
        ----------+--------------------+--------
         testdb02 | user_to_be_dropped |
        (1 row)
      • Untuk oid=16416, keanggotaan role dalam pg_auth_members mencatat izin yang diberikan oleh akun user_to_be_dropped.

        SELECT oid, roleid::regrole, member::regrole, grantor::regrole FROM pg_auth_members WHERE oid = 16416;
          oid  |        roleid        |   member   |      grantor
        -------+----------------------+------------+--------------------
         16416 | user_to_be_dropped_2 | testdbuser | user_to_be_dropped
        (1 row)
    • Dependensi objek dalam satu database

      Bidang database yang tidak kosong menentukan database yang berisi objek dependen.

      • Untuk oid=2200, daftar kontrol akses dari public schema di testdb01 berisi entri untuk user_to_be_dropped.

        SELECT nspname, nspowner::regrole, nspacl FROM pg_namespace WHERE oid = 2200;
         nspname |  nspowner  |                                  nspacl
        ---------+------------+---------------------------------------------------------------------------
         public  | testdbuser | {testdbuser=UC/testdbuser,=U/testdbuser,user_to_be_dropped=UC/testdbuser}
        (1 row)
      • Untuk oid=16403, pemilik tabel test_nsp.test_tbl di testdb01 adalah user_to_be_dropped.

        SELECT relname, relnamespace::regnamespace, relowner::regrole, relacl FROM pg_class WHERE oid = 16403;
         relname  | relnamespace |      relowner      | relacl
        ----------+--------------+--------------------+--------
         test_tbl | test_nsp     | user_to_be_dropped |
        (1 row)

Langkah 2: Tangani objek dependen

Anda dapat menggunakan metode berikut berdasarkan kebutuhan bisnis Anda:

  • Jika jenis dependensi adalah ACL, Anda dapat mencabut izin yang sesuai.

  • Jika jenis dependensi adalah Owner, Anda dapat mentransfer kepemilikan ke akun lain atau menghapus dependensi terhadap akun tersebut.

Contoh:

  • Dependensi tipe ACL

    • Untuk oid=2200, cabut izin atas public schema di testdb01.

      SELECT nspname, nspowner::regrole, nspacl FROM pg_namespace WHERE oid = 2200;
       nspname |  nspowner  |                                  nspacl
      ---------+------------+---------------------------------------------------------------------------
       public  | testdbuser | {testdbuser=UC/testdbuser,=U/testdbuser,user_to_be_dropped=UC/testdbuser}
      (1 row)
      REVOKE ALL ON SCHEMA public FROM user_to_be_dropped;
    • Untuk oid=16399, cabut izin atas database testdb01.

      SELECT datname, datdba::regrole, datacl FROM pg_database WHERE oid = 16399;
       datname  |   datdba   |                                    datacl
      ----------+------------+------------------------------------------------------------------------------
       testdb01 | testdbuser | {=Tc/testdbuser,testdbuser=CTc/testdbuser,user_to_be_dropped=CTc/testdbuser}
      (1 row)
      REVOKE ALL ON DATABASE testdb01 from user_to_be_dropped;
    • oid=16416. Untuk ApsaraDB RDS for PostgreSQL 16 dan versi lebih baru, jika keanggotaan role terlibat, Anda harus beralih ke akun user_to_be_dropped dan mencabut izin dari akun istimewa (misalnya, testdbuser) milik user_to_be_dropped_2.

      \c testdb01 user_to_be_dropped;
      You are now connected to database "testdb01" as user "user_to_be_dropped".
      REVOKE user_to_be_dropped_2 FROM testdbuser cascade;
  • Dependensi tipe Owner

    Login ke database tempat objek dependen berada menggunakan akun istimewa.

    • Transfer kepemilikan objek ke akun lain.

      Untuk oid=16403, transfer kepemilikan tabel test_nsp.test_tbl di testdb01 ke akun lain (testdbuser dalam contoh ini).

      SELECT relname, relnamespace::regnamespace, relowner::regrole, relacl FROM pg_class WHERE oid = 16403;
       relname  | relnamespace |      relowner      | relacl
      ----------+--------------+--------------------+--------
       test_tbl | test_nsp     | user_to_be_dropped |
      (1 row)
      ALTER TABLE test_nsp.test_tbl OWNER TO testdbuser;
    • Hapus objek dependen

      • Hapus database testdb02.

        DROP DATABASE testdb02;
      • Hapus objek dengan oid=16402.

        SELECT nspname, nspowner::regrole, nspacl FROM pg_namespace WHERE oid = 16402;
         nspname  |      nspowner      | nspacl
        ----------+--------------------+--------
         test_nsp | user_to_be_dropped |
        (1 row)
        DROP SCHEMA test_nsp cascade;
      • Hapus objek dengan oid=16406.

        SELECT relname, relnamespace::regnamespace, relowner::regrole, relacl FROM pg_class WHERE oid = 16406;
         relname  | relnamespace |      relowner      | relacl
        ----------+--------------+--------------------+--------
         test_tbl | public       | user_to_be_dropped |
        (1 row)
        DROP TABLE public.test_tbl;

Hasil berikut dikembalikan:

 database | classname | oid | case
----------+-----------+-----+------
(0 rows)

Langkah 3: Hapus akun

Hapus akun yang diperlukan melalui Konsol ApsaraDB RDS atau dengan menjalankan pernyataan SQL. Contoh pernyataan SQL:

DROP USER user_to_be_dropped;

Hapus akun

Hapus akun yang diperlukan melalui Konsol ApsaraDB RDS atau dengan menjalankan pernyataan SQL. Contoh pernyataan SQL:

DROP USER user_to_be_dropped;