我在本地安装了 9.1 数据库,其中有几个表有 cca。300 条 mio 记录,数据库增长到大约 20 GB。之后我发出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;
Run Code Online (Sandbox Code Playgroud)
但是总共不到 1GB
SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database
Run Code Online (Sandbox Code Playgroud)
仍然显示大约 20 GB。任何建议非常感谢。
小智 29
虽然您没有说明,但我从您对您遵循的文档的引用中假设您已经对数据库和/或受影响的表进行了 VACUUM FULL。您也没有指定您使用的 postgresql 版本 - 我假设它 > 9.0(在此之前 VACUUM FULL 的行为有所不同)。
VACUUM FULL会将受影响的表重写为新文件,然后删除旧文件。但是,如果任何进程仍然打开旧文件,操作系统实际上不会删除该文件 - 直到最后一个进程关闭它。
如果可行,重新启动数据库将确保关闭所有打开的文件。
如果这不切实际,那么您可以验证这是否是您的问题,并找出打开了文件的进程。
如果使用 Linux(或大多数其他类 Unix 系统),您可以使用 'lsof' 命令获取在所有进程中打开的所有文件的列表。打开但已被删除的文件将在文件名后附加“(已删除)”。因此,您可以 grep lsof 的输出,查找已删除的文件,如下所示:
sudo lsof -u postgres | grep 'deleted'
Run Code Online (Sandbox Code Playgroud)
如果识别出仍然打开旧文件的进程,您可以使用 pg_terminate_backend 终止该进程:
SELECT pg_terminate_backend(xxx);
Run Code Online (Sandbox Code Playgroud)
其中 xxx 是进程的 PID,可在 lsof 输出中找到。
如果使用 Windows,则可以应用相同的原则,因为 postgres 使用 FILE_SHARE_DELETE 标志打开文件,这允许它删除在另一个进程中打开的文件。' handle ' 命令大致相当于 lsof,但我不确定您是否能判断文件是否被删除,因此可能需要一些额外的工作。
至于为什么任何此类进程会挂在旧文件句柄上,这是另一个问题。但是,在您在问题中引用的线程中,Tom Lane 似乎暗示它可能发生。
| 归档时间: |
|
| 查看次数: |
49670 次 |
| 最近记录: |