You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PostgreSQL 12 base目录大缓存文件问题及空间限制求助

解决PostgreSQL 12数据文件过大导致磁盘耗尽的问题

首先要纠正一个关键误解:你看到的/var/lib/postgresql/12/main/base/16384目录下的文件不是缓存文件,而是PostgreSQL存储数据库表、索引和大对象的实际数据文件。每个默认1GB的文件是PostgreSQL的标准关系文件(超过1GB会自动拆分,除非开启了large_file参数允许单个文件更大)。你说数据库“只有8MB”,大概率是忽略了某些大表、TOAST存储(用于存放大字段)或未清理的大对象。

第一步:定位大文件对应的数据库对象

先别直接删文件(会彻底损坏数据库),先搞清楚这些大文件属于什么:

  1. 找到16384对应的数据库名:

    -- 连接到PostgreSQL
    sudo -u postgres psql
    -- 查询数据库OID和名称映射
    SELECT oid, datname FROM pg_database;
    

    16384通常是默认的template1数据库,但也可能是你自己创建的某个库,记下来对应的datname

  2. 切换到该数据库,找出占用空间最大的对象:

    -- 切换目标数据库
    \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_limitshared_buffers等参数和数据文件大小无关(这些分别控制临时文件、共享内存缓存、WAL日志),要限制数据库空间,推荐用表空间+文件系统配额的方案:

  1. 创建一个单独的表空间目录:

    sudo mkdir /var/lib/postgresql/12/main/limited_tablespace
    sudo chown postgres:postgres /var/lib/postgresql/12/main/limited_tablespace
    
  2. 在PostgreSQL中创建表空间:

    CREATE TABLESPACE limited_space LOCATION '/var/lib/postgresql/12/main/limited_tablespace';
    
  3. 给该目录所在的分区设置磁盘配额(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行的softhard值为102400000(因为1块=1KB,100GB=10010241024 KB)。

  4. 将目标数据库或表迁移到这个受限表空间:

    -- 迁移整个数据库到受限表空间
    ALTER DATABASE your_target_db_name SET TABLESPACE limited_space;
    -- 或者只迁移大表
    ALTER TABLE your_large_table_name SET TABLESPACE limited_space;
    

紧急处理磁盘耗尽的情况

如果当前磁盘已经满到PostgreSQL无法启动:

  1. 先停止PostgreSQL服务:
    sudo systemctl stop postgresql@12-main
    
  2. 清理安全的临时文件:比如pg_wal目录中已经归档的旧WAL日志(如果没有主从复制,可删除最近几个以外的WAL,但风险较高,建议先备份),或者清理系统临时目录/tmp下的无用文件。
  3. 启动PostgreSQL后立即执行前面的清理步骤。

内容的提问来源于stack exchange,提问作者Marcin Zdunek

火山引擎 最新活动