PostgreSQL 14: 新增 pg_database_owner 默认角色

John Doe 七月 15, 2025

你想在 PostgreSQL 中添加一些用于监控或管理数据库的 SQL 函数吗?那么,你需要控制好它们的访问权限。

欢快奔跑的大象

特性提交日志

新增 “pg_database_owner” 默认角色。

该角色的成员隐含为当前数据库的所有者。预计在模板数据库中使用。一旦 pg_database_owner 在模板中拥有权限,从该模板实例化的数据库的每个所有者都将行使这些权限。

讨论:https://postgr.es/m/20201228043148.GA1053024@rfd.leadboat.com

示例

你可能知道,只要在 template1 数据库中创建了某些内容,当你使用默认选项创建新数据库时,新数据库会复制 template1 中的所有内容。有时候,我们可能会往 template1 添加一些监控函数或类似的东西。

让我们看看 pg_database_owner 是如何工作的。

假设我们有 3 个用户:redrock(超级用户)、test 和 test2。

当 test 或 test2 查询 pg_stat_activity 时,在 query 列中,他们通常会看到“权限不足”。

现在,我们以 redrock 的身份登录到 template1,并执行:

create function get_running_queries()
  returns table (pid int4, query text) as
$$
  select pid, query from pg_stat_activity
    where backend_type = 'client backend';
$$ language sql security definer;

revoke all on function get_running_queries() from public;

grant execute on FUNCTION get_running_queries() to pg_database_owner;

现在,当我们以 test 或 test2 的身份连接到 template1,并尝试使用这个函数时,会得到:

$ for u in test test2; do psql -d template1 -U $u -X -c 'select * from get_running_queries()'; done
ERROR:  permission denied for function get_running_queries
ERROR:  permission denied for function get_running_queries

但是,当我们创建一个以 test 为所有者的数据库:

create database test with owner test;

并在 test 数据库中重新进行测试时:

$ for u in test test2
do
    echo "===== user: $u ====="
    psql -d test -U $u -X -c 'select * from get_running_queries()'
    echo
done
===== user: test =====
  pid   |                 query
--------+---------------------------------------
 174949 | select * from get_running_queries()
 169886 | select pg_sleep(1000000);
 170124 | select * from pg_stat_activity ;
 170312 | create database test with owner test;
(4 rows)

===== user: test2 =====
ERROR:  permission denied for function get_running_queries

当然,这个例子相当简单,但是希望这能展示出可以实现的功能。

它允许轻松创建那些仅对数据库所有者可用、而对其他任何用户不可用的内容,无需在每个新数据库中手动授予权限。

非常不错的特性。感谢社区的所有相关人员。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/a14a0118a1fecf4066e53af52ed0f188607d0c4b