delete from
命令以从中删除所有记录(我应该使用truncate
,但我不知道)。因此,我对数据库进行了充分的清理以回收磁盘空间,但这无济于事。我的问题看起来与此相同,但是没有提供解决方案。我已经检查了该线程和有关“恢复磁盘空间”的文档,但是仍然找不到解决方案。我使用此代码获取所有表的大小 SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
AND C.relkind <> 'i'
AND nspname !~ '^pg_toast'
ORDER BY pg_total_relation_size(C.oid) DESC
LIMIT 15;
SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database
>仍显示约20 GB。任何建议,不胜感激。
#1 楼
尽管您没有声明,但是从您对文档的引用中,我认为您已经对数据库和/或受影响的表进行了VACUUM FULL。您还没有指定要使用的Postgresql版本-我将假定它是9.0以上(VACUUM FULL在此之前的行为有所不同)。VACUUM FULL会将受影响的表重写为新文件,然后删除旧文件。但是,如果任何进程仍打开了旧文件,则操作系统将不会真正删除该文件-直到最后一个进程将其关闭。
如果可行,重新启动数据库将确保所有打开的文件关闭。
如果这不切实际,那么您可以验证这是否是您的问题,并找出打开文件的进程。
如果使用Linux(或大多数其他类似Unix的系统),则可以使用“ lsof”命令获取在所有进程中打开的所有文件的列表。已打开但已删除的文件将在文件名后附加“(已删除)”。因此,您可以对lsof的输出进行grep,以查找已删除的文件,如下所示:
sudo lsof -u postgres | grep 'deleted'
如果它标识出仍然打开了旧文件的进程,则可以使用pg_terminate_backend终止该进程:
SELECT pg_terminate_backend(xxx);
其中xxx是该进程的PID,在lsof输出中找到。
如果使用Windows,可以应用相同的原理,因为postgres使用FILE_SHARE_DELETE标志打开文件,这使它可以删除在另一个进程中打开的文件。 “ handle”命令与lsof大致等效,尽管我不确定是否可以确定文件是否已删除,所以可能需要一些额外的工作。
这是另一个问题为什么任何这样的过程都会挂在旧文件句柄上。但是,在您引用的问题中,汤姆·莱恩(Tom Lane)似乎暗示它可能会发生。
评论
我必须紧急收回磁盘空间,因此删除了数据库并从备份中还原了它。但是,“解决方法”对于将来的案例仍然非常有价值。我的数据库是9.1,Win 8 64位,文件命名(打开文件的情况)是否适用于Linux?
–鸥
2014年1月13日在7:11
@arcull OK,我没有意识到您正在使用Windows。我在答案中添加了一些有关如何将其应用于Windows的信息。如果您认为这可能是一个有用的答案,请考虑投票,因为它可以使其他人更容易找到它。
–有害
2014年1月13日上午10:58
当VACUUM FULL花费的时间太长,并且您需要分段的解决方案(对于某些类型的数据)时,另一种选择是创建另一个表,复制内容,删除原始表,然后将新表重命名为旧名称。
–edgeoff
20年6月12日,0:44
评论
好吧,您的大小查询不包括:索引,pg_catalog中的表和information_schema中的表。因此,请通过删除WHERE子句中的限制来尝试查看是否有这些限制。请显示您的确切PostgreSQL版本(SELECT version()),以及您要“清空整个数据库”的确切操作,即确切的命令。如果可能,请运行VACUUM FULL VERBOSE; (无参数)并将输出粘贴到某个位置,然后在此处链接到它。尝试删除数据库。您也可以尝试转储数据库,然后还原它会丢弃垃圾。
@jb可以,但是没有必要。更好地了解问题所在。