DBAtlas · 数据库运维图谱

磁盘/表空间已满

症状

出现 'unable to extend'、'disk full'、'log file full' 错误;写入正在停止。

1. 不要惊慌;先找出是什么满了

是数据文件、事务日志、归档/redo 区域、临时空间还是操作系统磁盘?清理错了地方无济于事。在操作系统层面用 df -h 检查磁盘,并在数据库内查看空间相关视图。

2. 测量使用情况

哪个表空间/文件/目录满了,使用率是多少?

Oracle

SELECT d.tablespace_name, ROUND((1-(d.alloc-NVL(f.free,0))/d.maxb)*100,1) pct_free FROM (SELECT tablespace_name, SUM(bytes) alloc, SUM(GREATEST(bytes,maxbytes)) maxb FROM dba_data_files GROUP BY tablespace_name) d LEFT JOIN (SELECT tablespace_name, SUM(bytes) free FROM dba_free_space GROUP BY tablespace_name) f ON f.tablespace_name = d.tablespace_name;

PostgreSQL

SELECT datname, pg_size_pretty(pg_database_size(datname)) FROM pg_database ORDER BY 2 DESC; -- use OS df for the disk

MySQL

SELECT table_schema, ROUND(SUM(data_length+index_length)/1048576,1) mb FROM information_schema.tables GROUP BY table_schema ORDER BY mb DESC;

SQL Server

SELECT name, size/128.0 size_mb, size/128.0 - CAST(FILEPROPERTY(name,'SpaceUsed') AS int)/128.0 free_mb FROM sys.database_files;

Redis

INFO memory  # used_memory vs maxmemory

3. 找出最大的空间占用者

确定最大的表/段、最大的日志/归档文件以及不再需要的旧备份。大多数情况下,罪魁祸首是某张失控的表或累积的归档日志。

Oracle

SELECT segment_name, bytes/1048576 mb FROM dba_segments ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;

PostgreSQL

SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) FROM pg_statio_user_tables ORDER BY pg_total_relation_size(relid) DESC LIMIT 10;

SQL Server

SELECT TOP 10 OBJECT_NAME(object_id), SUM(reserved_page_count)*8/1024 mb FROM sys.dm_db_partition_stats GROUP BY object_id ORDER BY mb DESC;

4. 安全地回收空间(快速)

对于日志/归档:先备份,再清除旧的归档日志/备份(Oracle:RMAN delete archivelog;MSSQL:执行日志备份并收缩日志)。在 Redis 中:maxmemory-policy 与淘汰。切勿手动删除正在使用的数据文件;切勿在没有备份的情况下删除归档日志。

5. 永久扩容

为数据文件增加空间或启用自动扩展(Oracle:ALTER DATABASE DATAFILE ... AUTOEXTEND ON MAXSIZE)、扩大磁盘、添加表空间。修复根本原因:日志轮转、归档清理作业、保留策略。

6. 防止再次发生

设置磁盘使用率告警(80%/90% 阈值),自动化归档/日志清理,并明确定义保留策略。避免再次需要打开这份应急手册。

在 DBAtlas 中打开 →