我需要在没有可用磁盘空间的情况下运行 VACUUM FULL

Jus*_*yne 38 postgresql delete database-size alter-table vacuum

我有一张桌子占用了我们服务器上接近 90% 的高清空间。我决定删除几列以释放空间。但我需要将空间归还给操作系统。但是,问题是我不确定如果我运行 VACUUM FULL 并且没有足够的可用空间来制作表的副本会发生什么。

我知道不应使用 VACUUM FULL,但我认为这是这种情况下的最佳选择。

任何想法,将不胜感激。

我正在使用 PostgreSQL 9.0.6

Cra*_*ein 24

由于您没有足够的空间来运行 vacumm 或重建,您始终可以通过恢复来重建您的 postgresql 数据库。恢复数据库、表、索引将释放空间和碎片整理。之后,您可以设置自动维护以定期清理数据库。

1 备份 postgresql 服务器上的所有数据库

您需要将所有数据库备份到具有足够空间的分区。如果您使用的是 Linux,则可以使用 gzip 进一步压缩备份以节省空间

su - postgres
pg_dumpall | gzip -9 > /some/partition/all.dbs.out.gz
Run Code Online (Sandbox Code Playgroud)

2 备份您的配置文件

cp /path/to/postgresql/data_directory/*.conf /some/partition/
Run Code Online (Sandbox Code Playgroud)

3 停止 Postgresql

pg_ctl -D /path/to/postgresql/data_directory stop
Run Code Online (Sandbox Code Playgroud)

4 擦除数据目录的内容

rm -Rf /path/to/postgresql/data_directory/*
Run Code Online (Sandbox Code Playgroud)

5 运行 initdb 以重新初始化您的数据目录

initdb -D /path/to/postgresql/data_directory
Run Code Online (Sandbox Code Playgroud)

6 恢复配置文件

cp /some/partition/*.conf /path/to/postgresql/data_directory/*.conf 
Run Code Online (Sandbox Code Playgroud)

7 启动 PostgreSQL

pg_ctl -D /path/to/postgresql/data_directory start
Run Code Online (Sandbox Code Playgroud)

8 恢复您创建的所有数据库的转储

gunzip /some/partition/all.dbs.out.gz
psql -f /some/partition/all.dbs.out
Run Code Online (Sandbox Code Playgroud)

  • 效果很好,我只是建议跳过“gzip”部分以节省时间。 (2认同)

exh*_*uma 23

注意:我已经在 9.1 上测试过了。我这里没有 9.0 服务器。我很确定虽然它可以在 9.0 上运行。


注意(如@erny 的评论中所述):

Note that high CPU load due to I/O operations may be expected.
Run Code Online (Sandbox Code Playgroud)

通过使用临时表空间,您可以在几乎没有停机时间的情况下完成此操作。停机时间将以排他锁的形式出现。但只有在桌子上你才吸尘。因此,所有会发生的是,客户端查询时将只是等待锁被收购,如果他们访问相关表格。您不需要关闭现有连接。

但是要注意的一件事是,移动桌子和吸满真空本身需要先等待排他锁!


首先,您显然需要一些额外的存储空间。正如Stéphane评论中提到的,这需要至少是所讨论表格的两倍大,而VACUUM FULL不是完整副本。如果你很幸运并且可以动态地向机器添加磁盘,那么就这样做。在最坏的情况下,您可以只附加一个 USB 磁盘(虽然有风险且速度慢)!

接下来,挂载新设备并使其可用作表空间:

CREATE TABLESPACE tempspace LOCATION '/path/to/new/folder';
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法轻松列出表空间:

\db
Run Code Online (Sandbox Code Playgroud)

仔细检查表的当前表空间(您需要知道将其移回何处):

SELECT tablespace FROM pg_tables WHERE tablename = 'mytable';
Run Code Online (Sandbox Code Playgroud)

如果是NULL,它将位于默认表空间中:

SHOW default_tablespace;
Run Code Online (Sandbox Code Playgroud)

如果NULL为好,它可能会pg_default(查看官方文档的情况下,它的改变)。

现在把桌子移过去:

ALTER TABLE mytable SET TABLESPACE tempspace;
COMMIT;  -- if autocommit is off
Run Code Online (Sandbox Code Playgroud)

抽真空:

VACUUM FULL mytable;
Run Code Online (Sandbox Code Playgroud)

将其移回:

-- assuming you are using the defaults, the tablespace will be "pg_default".
-- Otherwise use the value from the SELECT we did earlier.
ALTER TABLE mytable SET TABLESPACE pg_default;
COMMIT;  -- if autocommit is off
Run Code Online (Sandbox Code Playgroud)

删除临时空间:

DROP TABLESPACE tempspace;
Run Code Online (Sandbox Code Playgroud)

  • 惊人的提示,感谢您的详细解释。请注意,在临时表空间上,您至少需要 ```size of table x 2```,因为 ```VACUUM FULL``` 正在制作表的完整副本。 (2认同)

小智 8

又快又脏:

  • 停止 Postgres
  • 将主数据库目录移动到另一个有足够空间进行清理的磁盘
  • 在 main 的原始位置中,添加一个指向新位置的符号链接
  • 真空
  • 删除符号链接并将主目录移回其原始位置
  • 启动 Postgres

例如,:

$ service postgresql stop $ mv /var/lib/postgresql/9.5/main /mnt/bigdisk $ ln -sr /mnt/bigdisk/main /var/lib/postgresql/9.5 $ vacuumdb --all --full $ rm /var/lib/postgresql/9.5/main $ mv /mnt/bigdisk/main /var/lib/postgresql/9.5 $ service postgresql start