ディスク / 表領域が満杯
'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 の回収を妨げている。