PostgreSQL 12 base目录大缓存文件问题及空间限制求助
解决PostgreSQL 12数据文件过大导致磁盘耗尽的问题
首先要纠正一个关键误解:你看到的/var/lib/postgresql/12/main/base/16384目录下的文件不是缓存文件,而是PostgreSQL存储数据库表、索引和大对象的实际数据文件。每个默认1GB的文件是PostgreSQL的标准关系文件(超过1GB会自动拆分,除非开启了large_file参数允许单个文件更大)。你说数据库“只有8MB”,大概率是忽略了某些大表、TOAST存储(用于存放大字段)或未清理的大对象。
第一步:定位大文件对应的数据库对象
先别直接删文件(会彻底损坏数据库),先搞清楚这些大文件属于什么:
找到16384对应的数据库名:
-- 连接到PostgreSQL sudo -u postgres psql -- 查询数据库OID和名称映射 SELECT oid, datname FROM pg_database;16384通常是默认的
template1数据库,但也可能是你自己创建的某个库,记下来对应的datname。切换到该数据库,找出占用空间最大的对象:
-- 切换目标数据库 \c your_target_db_name -- 查看前10大的表(含索引和TOAST) SELECT relname AS object_name, pg_size_pretty(pg_total_relation_size(relid)) AS total_size FROM pg_stat_user_tables ORDER BY pg_total_relation_size(relid) DESC LIMIT 10; -- 检查是否有大对象(比如存储的二进制文件) SELECT oid AS lo_id, pg_size_pretty(pg_total_relation_size(oid)) AS lo_size FROM pg_largeobject_metadata ORDER BY pg_total_relation_size(oid) DESC LIMIT 5;
第二步:安全清理冗余数据
根据上面的查询结果,针对性清理:
- 如果是废弃的大表:直接删除表(注意先备份重要数据)
DROP TABLE IF EXISTS your_large_table_name CASCADE; - 如果是表中冗余数据:先删除不需要的行,再执行
VACUUM FULL回收空间(注意:VACUUM FULL会锁表,建议在业务低峰期操作)DELETE FROM your_table_name WHERE your_cleanup_condition; VACUUM FULL your_table_name; - 如果是无用的大对象:删除对应的大对象
SELECT lo_unlink(lo_id) FROM pg_largeobject_metadata WHERE lo_id = your_target_lo_id;
第三步:限制数据库最大空间到100GB
你之前修改的temp_file_limit、shared_buffers等参数和数据文件大小无关(这些分别控制临时文件、共享内存缓存、WAL日志),要限制数据库空间,推荐用表空间+文件系统配额的方案:
创建一个单独的表空间目录:
sudo mkdir /var/lib/postgresql/12/main/limited_tablespace sudo chown postgres:postgres /var/lib/postgresql/12/main/limited_tablespace在PostgreSQL中创建表空间:
CREATE TABLESPACE limited_space LOCATION '/var/lib/postgresql/12/main/limited_tablespace';给该目录所在的分区设置磁盘配额(Ubuntu 18.04用quota工具):
# 安装quota工具 sudo apt-get install quota # 开启分区配额(先确认目录挂载点:df -h /var/lib/postgresql/12/main/limited_tablespace) sudo quotacheck -cug / sudo quotaon / # 编辑postgres用户的配额,设置硬限制为100GB sudo edquota -u postgres在弹出的编辑器中,修改
blocks行的soft和hard值为102400000(因为1块=1KB,100GB=10010241024 KB)。将目标数据库或表迁移到这个受限表空间:
-- 迁移整个数据库到受限表空间 ALTER DATABASE your_target_db_name SET TABLESPACE limited_space; -- 或者只迁移大表 ALTER TABLE your_large_table_name SET TABLESPACE limited_space;
紧急处理磁盘耗尽的情况
如果当前磁盘已经满到PostgreSQL无法启动:
- 先停止PostgreSQL服务:
sudo systemctl stop postgresql@12-main - 清理安全的临时文件:比如
pg_wal目录中已经归档的旧WAL日志(如果没有主从复制,可删除最近几个以外的WAL,但风险较高,建议先备份),或者清理系统临时目录/tmp下的无用文件。 - 启动PostgreSQL后立即执行前面的清理步骤。
内容的提问来源于stack exchange,提问作者Marcin Zdunek




