6

我正在尝试清理 heroku 上的 postgres 数据库,其中一些大对象已经失控,我想删除不再使用的大对象。

在我的开发机器上,我可以这样做:

select distinct loid from pg_largeobject 
Where loid Not In (select id from table )

然后我运行:

SELECT lo_unlink(loid)

在每个 ID 上。

但是在heroku上,我无法运行任何选择pg_largeobject,甚至

select * from pg_largeobject limit 1;

给我一个错误:

ERROR:  permission denied for relation pg_largeobject

pg_largeobject有什么建议可以解决这个问题,或者实际上为什么我们在 heroku 中没有读取权限?

4

1 回答 1

8

从 PostgreSQL 9.0 开始,非超级用户无法访问pg_largeobject. 这记录在发行说明中:

添加使用 GRANT/REVOKE (KaiGai Kohei) 控制大对象 (BLOB) 权限的功能

以前,任何数据库用户都可以读取或修改任何大对象。现在可以为每个大对象授予和撤销读取和写入权限,并跟踪大对象的所有权。

如果它适用于您的开发实例,则可能是因为它的版本8.4或更低,或者因为您以超级用户身份登录。

如果您无法在 heroku 上以超级用户身份登录,我想您可以使用 转储远程数据库pg_dump,然后在本地重新加载,将泄漏的 OID 识别为本地超级用户,将它们放入带有lo_unlink命令的脚本中,最后播放这个针对 heroku 实例的脚本。

更新:

根据 psql\dl命令查询数据库的方式,似乎pg_catalog.pg_largeobject_metadata可以通过以下查询检索所有大对象的 OID 和所有权:

SELECT oid as "ID",
  pg_catalog.pg_get_userbyid(lomowner) as "Owner",
  pg_catalog.obj_description(oid, 'pg_largeobject') as "Description"
  FROM pg_catalog.pg_largeobject_metadata   ORDER BY oid

因此,对于 9.0+ 的非超级用户,可以将查找泄漏的大对象的初始查询更改为:

select oid from pg_largeobject_metadata
 Where oid Not In (select id from table )

lomowner如有必要,可以添加一个条件来过滤特定用户拥有的大型对象。

于 2013-02-22T16:21:02.343 回答