尽pipe磁盘使用率低,但诊断PostgreSQL的磁盘空间不足错误

我有一个使用PostgreSQL 9.3数据库的Django Web应用程序,偶尔会引发错误:

File "/usr/local/my_site/.env/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__ six.reraise(dj_exc_type, dj_exc_value, traceback) File "/usr/local/my_site/.env/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute return self.cursor.execute(sql, params) OperationalError: could not write block 2432320 of temporary file: No space left on device HINT: Perhaps out of disk space? 

它运行在EC2 / RDS上,我找不到任何磁盘空间不足的东西。 EC2实例有一个9GB的驱动器,只有38%在使用。 RDS PostgreSQL数据库有20GB的存储空间,只有1%的使用率。 我认为这可能是EC2实例中的一个低inode问题,但是df -i显示只有33%被使用。

什么会造成这个错误?

你得到这个错误是因为PostgreSQL的空间不够用来写一个临时文件。 至less有一个查询会导致数据库偶尔写出一个对于可用空间来说太大的临时表。

默认情况下,postgresql为temp_tablespacesconfiguration使用一个空string; 这意味着临时表被写入默认表空间(也就是你的$ DATA_DIR)。 既然你正在使用RDS Postgres你将不得不看看使用什么设置

select * from pg_settings where name='temp_tablespaces';

考虑到所提到的块位置以及使用8192的RDS块大小。看起来您正在写出将近20GB的临时表,这并不意味着您拥有该表的数据库簇的数量。

这会build议你有一个病态的查询来build立一个临时表,这个临时表是数据库内容的一个倍数。 你应该尝试logging所有的查询到你的数据库( 见aws文档为例),看看你是否能够发现你不小心做了两个表的笛卡尔连接和筛选输出(或任何forms的坏的查询可能有采取)。

你可能想将temp_file_limit限制设置为一个合理的值(我会用4GB),但这只会使底层问题更加明显,因为你会提前触及限制。

真正的解决scheme是查找并隔离导致您使用所有临时空间的查询。 最简单的方法是得到它在SQL中,并找出为什么Django的ORM正在生产。