J'ai supprimé un utilisateur d'une base de données Amazon Redshift, mais l'utilisateur apparaît toujours dans la table pg_class

Date de la dernière mise à jour : 09/01/2020

Pourquoi les utilisateurs Amazon Redshift supprimés apparaissent-ils toujours dans la table pg_class, mais pas dans la table pg_user ?

Brève description

Les utilisateurs supprimés peuvent toujours apparaître dans la table pg_class lorsque l'utilisateur supprimé possède un objet dans une autre base de données du cluster. La commande DROP USER vérifie uniquement la base de données actuelle pour les objets détenus par l'utilisateur qui est sur le point d'être supprimé. Si l'utilisateur possède un objet dans une autre base de données, aucune erreur n'est déclenchée. Au lieu de cela, l'utilisateur supprimé conserve la propriété de l'objet et usesysid apparaît toujours dans la table pg_class.

Solution

Exécutez la commande suivante sur chaque base de données de votre cluster. Cette commande vérifie les objets détenus par des utilisateurs supprimés.

select distinct schemaname, tablename, tableowner from pg_tables where tableowner like '%unknown%';

Si un utilisateur supprimé possède toujours des objets dans une base de données, vous obtenez un résultat similaire à ce qui suit. Le propriétaire de table est « inconnu », car le propriétaire a été supprimé de la table pg_user, où les noms d'utilisateur sont stockés.

demo_localdb=# select distinct schemaname, tablename, tableowner from pg_tables where tableowner like '%unknown%'; 
 schemaname |    tablename    |    tableowner     
------------+-----------------+-------------------
 demo_local | orders_nocomp_2 | unknown (UID=114)
 demo_local | orders_nocomp_3 | unknown (UID=115)
(2 rows)

Utilisez la commande ALTER TABLE pour transférer la propriété des objets. Dans l'exemple suivant, le nouveau propriétaire est userc.

alter table demo_local.orders_nocomp_2 owner to userc;

Prévention

Avant de supprimer un utilisateur, exécutez la requête suivante pour trouver les objets qui lui appartiennent. (Pour ce faire, vous pouvez également utiliser la vue v_find_dropuser_objs.) Dans l'exemple suivant, l'utilisateur est labuser.

SELECT decode(pgc.relkind,
             'r','Table',
             'v','View'
       ) ,
       pgu.usename,
       pgu.usesysid,
       nc.nspname,
       pgc.relname,
       'alter table ' || QUOTE_IDENT(nc.nspname) || '.' || QUOTE_IDENT(pgc.relname) || ' owner to '
FROM pg_class pgc,
     pg_user pgu,
     pg_namespace nc
WHERE pgc.relnamespace = nc.oid
AND   pgc.relkind IN ('r','v')
AND   pgu.usesysid = pgc.relowner
AND nc.nspname NOT ILIKE 'pg\_temp\_%'
AND pgu.usename = 'labuser'

Cette requête peut ne pas trouver d'utilisateurs qui possèdent des schémas créés avec une commande similaire à la suivante. Dans cet exemple, labuser est le propriétaire du schéma.

create schema demo_local authorization labuser;

Les utilisateurs avec des autorisations de niveau schéma ne peuvent pas être supprimés, sauf si le schéma est transféré à un nouveau propriétaire. Voici un exemple de transfert de propriété vers userc :

alter table demo_local.orders_nocomp_2 owner to userc;