在 TRUNCATE 145GB table 之后,Postgres 没有释放 space 到 OS

Postgres did not free the space to OS after TRUNCATE of a 145GB table

我今天 运行 得到了 145GB table,但是 space 没有 return 到 OS。我已经在数据库内部进行了验证,table 现在是空的。

尽管 space 没有被释放到 OS,我注意到 运行 在分区中执行 du 命令已经报告少了 145GB,但是当我 运行 df -h 它没有。 145GB 的差异不可能是因为 inode 大小。

我运行在 CentOS 7 中使用 Postgres 9.3 数据库连接 Mirth 服务器。

知道为什么 space 没有被释放吗?

当您删除或截断 table 时,PostgreSQL 不会 return 它的 space 到 OS
它只是将每一行标记为 "deleted".
当你插入一个新行时,PostgreSQL 重新使用 "deleted" space 来存储一个新数据。

要释放这样的 "deleted" space,您应该使用 VACUUM FULL
https://www.postgresql.org/docs/devel/sql-vacuum.html

您必须等到 t运行saction 被提交才能删除文件。

请参阅 ExecuteTruncateGuts 中的以下评论:

/*
 * Need the full transaction-safe pushups.
 *
 * Create a new empty storage file for the relation, and assign it
 * as the relfilenode value. The old storage file is scheduled for
 * deletion at commit.
 */

但既然你说 du 不再报告 space,那么一定是以下情况之一:

  • 运行行动 运行 TRUNCATE 仍然开放。

  • 其他东西打开了文件。直到最后一个(硬)link 消失并且最后一个进程关闭它,UNIX 才真正删除该文件。症状是 df 显示文件仍然存在,但 du 没有列出它。

也许不仅有大表,还有视图

你应该 运行 这个 SQL 来检查哪个 table/view 正在占用你的磁盘页面。

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 100;