DBAtlas · データベース運用アトラス

ディスク / 表領域が満杯

'unable to extend'、'disk full'、'could not extend'、'log full' が発生した。慌てない: まず何が満杯なのかを特定し、安全に領域を回収してから、恒久的に修正する。

何が満杯か?

誤った場所を整理しても効果はない。まず使用量を測定する: データファイル、トランザクションログ、アーカイブ / redo、temp、それとも OS のディスクか?

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 が満杯
  • OS のディスクが満杯 (DB ではない)

最大の消費者は何か?

ほとんどの場合、暴走した単一のテーブル / セグメントが原因である。最も大きいものを特定する。

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) が満杯
  • 長時間オープン中のトランザクションがログを保持している

根本原因: 暴走したテーブル / セグメント

単一のオブジェクトが予期せず増大した (制御されない挿入、一度も削除されないキュー / ログテーブル)。

根本原因: 実際の容量不足

通常の増加であり、領域を追加する必要がある。

根本原因: 肥大化 (bloat) / デッド行

削除 / 更新された行の領域が回収されていない。

根本原因: temp / undo が満杯

大きなソート / ハッシュ、または長時間オープン中のトランザクションが一時領域を埋めた。

根本原因: OS のディスクが満杯

問題は DB ではなく、オペレーティングシステムのディスクにある。ログ、コアダンプ、古いバックアップ、トレースファイルが領域を占めている可能性がある。

根本原因: ログバックアップが取得されていない (SQL Server)

FULL 復旧モデルでは、ログバックアップを取得しないとログは無制限に増大する。

根本原因: 放置されたレプリケーションスロット (PG)

停滞した (非アクティブな) スロットが WAL の削除を妨げ、pg_wal を肥大化させる。

根本原因: アーカイブログ領域 (FRA) が満杯 (Oracle)

アーカイブログが蓄積して FRA が満杯になった。アーカイバが停止すると、データベースは書き込みを受け付けなくなることがある。

根本原因: 長時間オープン中のトランザクション

最も古いアクティブなトランザクションが、ログ / undo の回収を妨げている。

DBAtlas で開く →