我正在尝试清理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
有关如何解决此问题的任何建议,或者甚至是我们在heroku中pg_largeobject
没有读取权限的原因?
答案 0 :(得分:8)
自PostgreSQL 9.0以来,非超级用户无法访问pg_largeobject
。这在发行说明中有记录:
添加控制大对象(BLOB)权限的功能 GRANT / REVOKE(KaiGai Kohei)
以前,任何数据库用户都可以读取或修改任何大对象。 现在可以根据大型授予和撤销读写权限 对象,跟踪大对象的所有权。
如果它适用于您的开发实例,则可能是因为它的版本为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
上的条件来过滤特定用户拥有的大对象。