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


27

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

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

任何想法,将不胜感激。

我正在使用PostgreSQL 9.0.6

Answers:


19

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

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

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

su - postgres
pg_dumpall | gzip -9 > /some/partition/all.dbs.out.gz

2备份您的配置文件

cp /path/to/postgresql/data_directory/*.conf /some/partition/

3停止Postgresql

pg_ctl -D /path/to/postgresql/data_directory stop

4擦除数据目录的内容

rm -Rf /path/to/postgresql/data_directory/*

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

initdb -D /path/to/postgresql/data_directory

6恢复配置文件

cp /some/partition/*.conf /path/to/postgresql/data_directory/*.conf 

7启动Postgresql

pg_ctl -D /path/to/postgresql/data_directory start

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

gunzip /some/partition/all.dbs.out.gz
psql -f /some/partition/all.dbs.out

1
谢谢,这是我最后要做的,有一些不同。我只是在备份后删除了数据库。然后创建一个新的并还原它。
贾斯汀2012年

别客气。我认为删除数据目录的内容并执行initdb就足够了。
Craig Efrein

效果很好,我只建议跳过该gzip部分以节省时间。
拉斐尔·巴博萨

17

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


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

Note that high CPU load due to I/O operations may be expected.

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

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


首先,您显然需要一些额外的存储空间。正如Stéphane评论中提到的那样,此表的大小至少应为VACUUM FULL完整表的两倍。如果幸运的话,可以将磁盘动态添加到计算机中,请执行此操作。在最坏的情况下,您只能连接USB磁盘(虽然速度较慢且速度慢)!

接下来,安装新设备并将其用作表空间:

CREATE TABLESPACE tempspace LOCATION '/path/to/new/folder';

您可以使用以下命令轻松列出表空间:

\db

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

SELECT tablespace FROM pg_tables WHERE tablename = 'mytable';

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

SHOW default_tablespace;

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

现在将桌子移到上方:

ALTER TABLE mytable SET TABLESPACE tempspace;
COMMIT;  -- if autocommit is off

吸尘:

VACUUM FULL mytable;

将其移回:

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

删除临时空间:

DROP TABLESPACE tempspace;

注意:此举似乎在原始数据目录中使用了更多的磁盘空间...
克里斯·威瑟斯

刚刚在9.3上进行了测试,它就像魅力一样工作。
Bartek Jablonski,

在9.1上成功用于生产。更改表空间后,将释放原始使用的空间。请注意,可能会由于I / O操作而导致较高的CPU负载。
erny

2
惊人的提示,感谢您的详细说明。请注意,在临时表空间上,您至少需要size of table x 2,因为它VACUUM FULL正在制作表的完整副本。
斯特凡

谢谢@Stéphane。我将信息添加到主体中。
展览

2

快速又肮脏:

  • 停止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


0

如果您有足够的磁盘空间来执行转储和还原,则应该有足够的磁盘空间来执行vacuumdb --full。问题在于vacuumdb --full将复制整个数据文件。因此,您可以做的是:

  1. 将保存巨大表的文件复制到其他驱动器,例如,速度更慢,更大的驱动器。
  2. 建立从原始位置到另一驱动器上新位置的符号链接。
  3. 运行vacuumdb --full,现在它应该从另一个磁盘读取数据,并将最终表写入原始数据磁盘。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.