磁盘/表空间已满
出现了 'unable to extend'、'disk full'、'could not extend' 或 'log full'。不要慌:先找出是什么满了,安全地回收空间,再做永久修复。
什么满了?
清理错了地方无济于事。先测量使用情况:是数据文件、事务日志、归档/redo、temp,还是操作系统磁盘?
SELECT d.tablespace_name, ROUND((1-(d.alloc-NVL(f.free,0))/d.maxb)*100,1) AS 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 ORDER BY pct_free;- 数据文件/表空间已满
- 事务日志/归档-redo 已满
- temp/undo 已满
- 操作系统磁盘已满(不是数据库)
最大的占用者是什么?
大多数情况下罪魁祸首是某一个失控的表/段。找出最大的那些。
SELECT segment_name, segment_type, ROUND(bytes/1048576,1) AS mb FROM dba_segments ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;- 有一个意外巨大/失控的表
- 正常增长,空间确实用完了
- 死行过多/膨胀(bloat)
日志为什么在增长?
在最老的活动事务/备份完成之前,日志/归档无法清理。它为什么会累积?
SELECT name, log_reuse_wait_desc FROM sys.databases WHERE name=DB_NAME(); -- why can it not be truncated?- MSSQL:没有执行日志备份(LOG_BACKUP)
- PG:停滞的复制槽保留着 WAL
- Oracle:归档日志区(FRA)已满
- 长时间打开的事务占住了日志
根本原因:失控的表/段
某个对象意外增长(不受控的插入、从未清理的队列/日志表)。
根本原因:确实需要扩容
正常增长;必须增加空间。
根本原因:膨胀/死行
已删除/更新的行所占空间未被回收。
根本原因:temp/undo 已满
大型排序/哈希或长时间打开的事务占满了临时空间。
根本原因:操作系统磁盘已满
问题出在操作系统磁盘上,而不是数据库。日志、core dump、旧备份或跟踪文件可能占用了空间。
根本原因:未执行日志备份(SQL Server)
在 FULL 恢复模式下,若不执行日志备份,日志会无限增长。
根本原因:被遗弃的复制槽(PG)
停滞(非活动)的复制槽会阻止 WAL 被删除,并撑大 pg_wal。
根本原因:归档日志区(FRA)已满(Oracle)
归档日志累积导致 FRA 已满;归档进程一旦停滞,数据库可能停止接受写入。
根本原因:长时间打开的事务
最老的活动事务阻止了日志/undo 被回收。