Jedes Datenbankobjekt in PostgreSQL hat einen Owner — die Rolle, der es „gehört”. Owner ist kein Privileg, das man via GRANT bekommt: es ist ein eigener Status, der sich beim Erstellen aus dem aktuellen User ergibt und nur per ALTER … OWNER TO weitergereicht werden kann. Wer Ownership versteht, versteht auch, warum man manche Rollen nicht so einfach loswird.
Was Owner können dürfen
Der Owner eines Objekts darf:
- das Objekt droppen (
DROP TABLE,DROP FUNCTION, …) - es umbenennen (
ALTER … RENAME TO) - es ändern (Spalten hinzufügen, Constraints, …)
- den Owner wechseln an eine andere Rolle, in der er Mitglied ist
- seinerseits Privilegien an andere vergeben (
GRANT)
Diese Rechte bekommt niemand sonst — auch ein User mit ALL PRIVILEGES darf eine Tabelle nicht droppen, wenn er nicht Owner ist. Es gibt nur zwei Ausnahmen: Superuser (dürfen alles) und Mitglieder der Owner-Rolle (über Inheritance).
CREATE ROLE app_owner;
CREATE ROLE app_user LOGIN PASSWORD 'changeme';
SET ROLE app_owner;
CREATE TABLE orders (id serial primary key, total numeric);
-- orders gehoert jetzt app_owner
GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO app_user;
SET ROLE app_user;
DELETE FROM orders; -- OK (DELETE-Privileg)
DROP TABLE orders; -- ERROR: must be owner of table ordersDefault-Owner
Wenn du CREATE TABLE foo (...) ohne weiteres ausführst, wird der aktuelle Effektiv-User (current_user) zum Owner. Bei einem SET ROLE app_owner; CREATE TABLE …;-Pattern landet das Eigentum entsprechend bei app_owner.
Das ist wichtig für saubere Setups: Migrations-Tools sollten unter dem Schema-Owner laufen, damit alle erzeugten Objekte zentral diesem User gehören. Sonst hast du nach drei Migrationen eine Mischung von Tabellen-Ownern, die zu späteren Problemen führt.
Owner ändern
ALTER TABLE orders OWNER TO app_owner;
ALTER FUNCTION calculate_tax(numeric) OWNER TO app_owner;
ALTER SCHEMA app OWNER TO app_owner;
ALTER DATABASE myapp OWNER TO app_owner;Voraussetzungen, um den Owner zu wechseln:
- Du musst aktueller Owner sein (oder Superuser).
- Du musst Mitglied der Ziel-Rolle sein.
- Bei
ALTER DATABASE … OWNER TObrauchst du zusätzlichCREATEDB-Recht oder Superuser-Status.
Was passiert beim DROP des Owners?
Hier liegt der häufigste Stolperstein. Wenn du eine Rolle droppen willst, die noch Objekte besitzt, lehnt Postgres ab:
myapp=# DROP ROLE app_owner;
ERROR: role "app_owner" cannot be dropped because some objects depend on it
DETAIL: owner of table orders, owner of schema app, ...Postgres weigert sich aus gutem Grund: würden die Objekte einfach „herrenlos” sein, könnte niemand mehr sicher mit ihnen arbeiten. Du musst also vorher den Besitz übertragen oder die Objekte droppen.
REASSIGN OWNED + DROP OWNED — das Aufräum-Pattern
Postgres bietet zwei Befehle, die diesen Job übernehmen:
-- 1. Alle Objekte, die app_owner gehoeren, an postgres uebertragen:
REASSIGN OWNED BY app_owner TO postgres;
-- 2. Restliche Privilegien und Default-Privileges der Rolle aufraeumen:
DROP OWNED BY app_owner;
-- 3. Jetzt klappt der DROP:
DROP ROLE app_owner;Was hier passiert:
REASSIGN OWNEDüberträgt das Eigentum aller Objekte, dieapp_ownerin der aktuellen Datenbank besitzt, an die Ziel-Rolle.DROP OWNEDentfernt zusätzlich alle Privilegien, die der Rolle in dieser Datenbank vergeben wurden — sowohl aktive (GRANT … TO app_owner) als auch zukünftige (ALTER DEFAULT PRIVILEGES … GRANTED BY app_owner).- Erst dann darf
DROP ROLEdie Rolle entfernen.
Wichtig: Beide Befehle wirken nur in der aktuellen Datenbank. Wenn die Rolle in mehreren Datenbanken Objekte besitzt, musst du dich der Reihe nach mit jeder verbinden und den Vorgang wiederholen.
Owner-Inspektion im Katalog
Wer wissen will, wem was gehört, fragt den Systemkatalog:
SELECT n.nspname AS schema, c.relname AS object,
pg_get_userbyid(c.relowner) AS owner, c.relkind
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname NOT IN ('pg_catalog','information_schema')
AND c.relkind IN ('r','p','v','m','S')
ORDER BY 1, 2;relkind zeigt: r = ordentliche Tabelle, p = partitionierte Tabelle, v = View, m = Materialized View, S = Sequence.
Für Schemas direkt:
SELECT nspname AS schema, pg_get_userbyid(nspowner) AS owner
FROM pg_namespace
WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema';Häufige Stolperfallen
Owner-Status taucht nicht in pg_class.relacl auf.
\dp my_table zeigt eine Spalte „Access privileges” — der Owner steht da nicht drin. Owner ist ein eigenes Feld (relowner). Wer per \d oder \dp nicht den Owner sieht, fragt mit \d+ oder direkt im Katalog nach.
ALTER OWNER scheitert, wenn du nicht Mitglied der Ziel-Rolle bist.
Du kannst Eigentum nur an eine Rolle übertragen, in der du selbst Mitglied bist (oder Superuser). Sonst könnte man Objekte beliebig „verschenken” — was die Aufräum-Konsistenz brechen würde. Vor ALTER … OWNER TO also kurz \du und prüfen.
REASSIGN OWNED arbeitet nur in der aktuellen Datenbank.
Klassischer Fehler: REASSIGN OWNED BY old_user TO postgres; wird in myapp ausgeführt, dann DROP ROLE old_user versucht — und Postgres bemängelt weiterhin Abhängigkeiten, weil old_user in analytics_db ebenfalls Tabellen besitzt. Lösung: in jede betroffene Datenbank verbinden und den Befehl wiederholen.
DROP OWNED loescht auch Default-Privileges.
Wenn app_owner mal ein ALTER DEFAULT PRIVILEGES FOR ROLE app_owner GRANT … TO app_user gesetzt hat, entfernt DROP OWNED BY app_owner auch diese Regel. Das ist gewollt — sonst hinge die Default-Privilege-Definition an einer nicht mehr existierenden Rolle.
Owner-Wechsel ist nicht reversibel ohne Wissen.
Wer „mal eben” alle Tabellen einer App von old_user auf postgres schiebt, hat eine durcheinander gewürfelte Eigentümer-Landschaft. Das ist gefährlich, wenn neue Migrationen mit Annahmen über den Schema-Owner laufen. Faustregel: Eigentum gehört zur Architektur — nicht ins Reaktive.
Cloud-Postgres limitiert OWNER-Operationen.
Auf RDS/Cloud SQL kannst du Objekte nicht ohne weiteres an postgres (Cloud-Superuser) übergeben — der Anbieter-User ist meist rds_superuser o. ä. Vor dem Aufräumen prüfen, welche Master-Rolle vorgesehen ist, sonst wirst du den User nie ganz los.
Weiterführende Ressourcen
Externe Quellen
- Database Roles – Object Ownership
- REASSIGN OWNED – PostgreSQL Documentation
- DROP OWNED – PostgreSQL Documentation
- ALTER TABLE … OWNER TO
- Dropping Roles – PostgreSQL Documentation