尽管磁盘使用率较低,但仍可从 PostgreSQL 诊断磁盘空间不足错误

尽管磁盘使用率较低,但仍可从 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%。

什么原因会导致这个错误?

答案1

您收到此错误是因为 PostgreSQL 没有足够的空间来写入临时文件。您至少有一个查询导致数据库偶尔写出一个对于可用空间来说太大的临时表。

默认情况下,postgresql 使用空字符串进行配置temp_tablespaces;这意味着临时表将写入默认表空间(即您的 $DATA_DIR )。由于您使用的是 RDS Postgres,因此您必须使用以下命令查看该设置的内容

select * from pg_settings where name='temp_tablespaces';

给定提到的块位置并使用 8192 的 RDS 块大小。看起来您正在写出近 20GB 的临时表,这并非巧合,这正是该数据库集群的表空间量。

这表明您有一个病态查询,它会构建一个临时表,该表是数据库内容的倍数。您应该尝试记录进入数据库的所有查询(请参阅 aws 文档作为示例),看看您是否可以发现您意外地对两个表进行了笛卡尔连接并过滤了输出(或您的错误查询可能采用的任何形式)。

您可能希望将temp_file_limit限制设置为一个合理的值(我会选择 4GB),但这只会使潜在的问题更加明显,因为您会更早地达到限制。

真正的解决方案是找到并隔离导致您使用所有临时空间的查询。最简单的方法是将其放入 SQL 中并找出 Django ORM 产生这种情况的原因。

相关内容