【Oracle】ORA-30036の原因と解決方法|UNDO表領域不足・長時間トランザクション・確認SQL

【Oracle】ORA-30036の原因と解決方法|UNDO表領域不足・長時間トランザクション・確認SQL Oracle

ORA-30036: unable to extend segment by ... in undo tablespace ... は、OracleがUNDO表領域内のUNDOセグメントを拡張できないときに発生するエラーです。INSERT、UPDATE、DELETE、MERGE、Data Pump、バッチ更新、長時間トランザクションなどでUNDOを大量に使うと、処理が途中で止まります。

Oracle公式のエラーメッセージでも、原因は「指定されたUNDO表領域に空きがないこと」、対処は「UNDO表領域に領域を追加する、またはアクティブなトランザクションのCOMMITを待つこと」とされています。ただし、本番では単純にデータファイルを足すだけでは再発します。どの処理がUNDOを消費しているか、AUTOEXTENDの上限に達していないか、UNDO_RETENTIONRETENTION GUARANTEE が効いていないかまで確認します。

表領域全体の考え方は Oracle表領域完全ガイド、容量不足の緊急対応は Oracle容量不足の緊急対応完全ガイド、UNDOと大量DMLの設計は 大量データ処理のコミット頻度とUNDO最適化 もあわせて確認してください。

この記事で整理すること

  • ORA-30036が発生する仕組み
  • まず止血するためのUNDO表領域追加・AUTOEXTEND設定
  • UNDO使用状況、ACTIVE/UNEXPIRED/EXPIREDの確認SQL
  • 長時間トランザクションと大量DMLの見つけ方
  • UNDO_RETENTIONとRETENTION GUARANTEEの注意点
  • ORA-01555やORA-01652との違い
  • 再発防止の監視SQLと設計チェック
スポンサーリンク

最初に結論:止血は領域追加、再発防止は原因特定

ORA-30036が本番で出ている最中は、まず処理を再開できる状態にする必要があります。最短の止血はUNDO表領域へのデータファイル追加、既存データファイルの拡張、AUTOEXTEND上限の見直しです。一方で、根本原因は長時間トランザクション、大量DML、COMMIT粒度、UNDO保持期間、領域設計のいずれかにあります。

すぐ処理を動かしたいUNDO表領域にデータファイルを追加する、既存ファイルを拡張する、AUTOEXTENDのMAXSIZEを見直します。
原因を切り分けたいDBA_UNDO_EXTENTSV$UNDOSTATV$TRANSACTIONV$SESSION を確認します。
再発を防ぎたいバッチのCOMMIT粒度、長時間クエリ、UNDO_RETENTION、RETENTION GUARANTEE、UNDO表領域サイズを見直します。
関連エラーと切り分けたいTEMP不足の ORA-01652、古いUNDOが消えた ORA-01555、通常表領域不足とは対処が違います。

TEMP表領域不足は ORA-01652の原因と解決方法、スナップショットが古すぎるエラーは ORA-01555完全ガイド が近いテーマです。

原因別の判断フロー

ORA-30036が出たときは、いきなりパラメータを変えるより、どの種類の不足かを短時間で分けます。判断の軸は、データファイル上限、ACTIVEなUNDO、UNEXPIREDなUNDO、発生時間帯の4つです。

データファイルが上限autoextensible がNO、または bytesmaxbytes に近い場合です。領域追加やMAXSIZE見直しが第一候補です。
ACTIVEが大きい未COMMITの大量DMLや長時間トランザクションがUNDOを握っています。V$TRANSACTION で対象セッションを確認します。
UNEXPIREDが大きいUNDO_RETENTIONやRETENTION GUARANTEE、長時間クエリの影響を疑います。ORA-01555とのバランスも見ます。
特定時間だけ増えるData Pump、月次バッチ、洗い替え、集計更新などのジョブ重複を疑います。時間帯をずらすだけで改善することがあります。

ORA-30036の意味

UNDOは、更新前のデータを保持する領域です。OracleはROLLBACK、一貫性読み取り、Flashback QueryなどのためにUNDOを使います。DMLが増えるほどUNDOは増え、処理がCOMMITまたはROLLBACKされるまではACTIVEなUNDOとして保持されます。

ORA-30036は、UNDO表領域に新しいUNDO領域を確保できなかったことを示します。つまり、更新処理に必要なUNDOを置く場所が足りません。空き領域がない、AUTOEXTENDできない、アクティブなトランザクションが領域を握っている、保持すべきUNDOが多すぎる、といった状態で起きます。

まず確認するエラーメッセージ

エラーメッセージには、どのUNDO表領域で、どれだけ拡張しようとして失敗したかが出ます。まず表領域名を控えます。

ora-30036-message.txt
ORA-30036: unable to extend segment by 128 in undo tablespace 'UNDOTBS1'

この例では、UNDOTBS1 というUNDO表領域で拡張に失敗しています。以降の確認SQLでは、この表領域を中心に見ます。

止血:UNDO表領域に領域を追加する

本番で処理が止まっている場合、まず空きを作ります。ディスク容量に余裕があること、バックアップや監視の運用に問題がないことを確認したうえで実行します。

既存データファイルを拡張する

resize-undo-datafile.sql
ALTER DATABASE DATAFILE '/u01/oradata/ORCL/undotbs01.dbf'
  RESIZE 20G;

データファイルを追加する

add-undo-datafile.sql
ALTER TABLESPACE UNDOTBS1
  ADD DATAFILE '/u01/oradata/ORCL/undotbs02.dbf'
  SIZE 10G
  AUTOEXTEND ON
  NEXT 512M
  MAXSIZE 50G;

AUTOEXTENDを有効化する

enable-undo-autoextend.sql
ALTER DATABASE DATAFILE '/u01/oradata/ORCL/undotbs01.dbf'
  AUTOEXTEND ON
  NEXT 512M
  MAXSIZE 50G;

AUTOEXTEND ON は便利ですが、無制限に伸ばす設計は危険です。OSやASMの領域まで使い切ると、別の障害に広がります。必ず MAXSIZE を決め、監視で上限に近づいたことを検知できるようにします。表領域の空き容量確認は 表領域の使用状況を確認するSQLまとめ も参考になります。

UNDO表領域の現在サイズを確認する

止血後、まず現在のUNDO表領域とデータファイルの状態を確認します。CDB/PDB構成では、対象PDBで確認するか、必要に応じてCDBビューを使います。

undo-datafile-check.sql
SELECT p.value AS current_undo_tablespace
FROM v$parameter p
WHERE p.name = 'undo_tablespace';

SELECT tablespace_name,
       file_name,
       ROUND(bytes / 1024 / 1024) AS current_mb,
       autoextensible,
       ROUND(maxbytes / 1024 / 1024) AS max_mb,
       ROUND(increment_by * 8 / 1024) AS next_mb
FROM dba_data_files
WHERE tablespace_name = (
  SELECT value
  FROM v$parameter
  WHERE name = 'undo_tablespace'
)
ORDER BY file_name;

bytes が現在サイズ、maxbytes がAUTOEXTEND時の上限です。autoextensible がYESでも、maxbytes に達していれば拡張できません。

現在の空きと上限をまとめて見る

undo-space-summary.sql
SELECT df.tablespace_name,
       ROUND(SUM(df.bytes) / 1024 / 1024) AS current_mb,
       ROUND(SUM(df.maxbytes) / 1024 / 1024) AS max_mb,
       MAX(df.autoextensible) AS autoextensible
FROM dba_data_files df
WHERE df.tablespace_name = (
  SELECT value
  FROM v$parameter
  WHERE name = 'undo_tablespace'
)
GROUP BY df.tablespace_name;

UNDOのACTIVE/UNEXPIRED/EXPIREDを確認する

DBA_UNDO_EXTENTS を見ると、UNDO領域がどの状態で使われているかを確認できます。ORA-30036の切り分けでは、ACTIVEが多いのか、UNEXPIREDが多いのかが重要です。

undo-extent-status.sql
SELECT tablespace_name,
       status,
       ROUND(SUM(bytes) / 1024 / 1024) AS mb
FROM dba_undo_extents
GROUP BY tablespace_name, status
ORDER BY tablespace_name, status;

-- 状態の見方
-- ACTIVE    : 現在のトランザクションが使用中
-- UNEXPIRED : 保持期間内で、読み取り一貫性のために残している
-- EXPIRED   : 必要なら再利用できる

ACTIVEが大きい場合は、実行中のDMLや未COMMITトランザクションが領域を使っています。UNEXPIREDが大きい場合は、UNDO_RETENTIONや長時間クエリ、RETENTION GUARANTEEの影響を確認します。EXPIREDが十分あるのにエラーが出る場合は、断片化やファイル上限、別の表領域を見ている可能性もあります。

UNDOを多く使っているトランザクションを探す

ORA-30036の原因が長時間トランザクションや大量DMLなら、対象セッションを特定します。すぐにKILLするのではなく、業務影響、処理内容、再実行可否を確認してから判断します。

find-undo-heavy-transaction.sql
SELECT s.sid,
       s.serial#,
       s.username,
       s.program,
       s.module,
       s.sql_id,
       t.start_time,
       t.used_ublk,
       t.used_urec,
       ROUND(t.used_ublk * TO_NUMBER(p.value) / 1024 / 1024) AS undo_mb
FROM v$transaction t
JOIN v$session s
  ON s.taddr = t.addr
JOIN v$parameter p
  ON p.name = 'db_block_size'
ORDER BY t.used_ublk DESC;

USED_UBLKUSED_UREC が大きいセッションほどUNDOを多く消費しています。アプリケーション側で DBMS_APPLICATION_INFO のMODULE/ACTIONを設定していると、どの処理か追いやすくなります。運用観測性は PL/SQLインストゥルメンテーション設計 が関連します。

UNDOの発生傾向をV$UNDOSTATで見る

V$UNDOSTAT は、UNDO使用量、チューニングされたUNDO保持時間、ORA-01555発生数などを見るためのビューです。直近だけでなく、いつUNDO圧迫が起きやすいかを確認できます。

undostat-trend.sql
SELECT begin_time,
       end_time,
       undoblks,
       txncount,
       maxquerylen,
       tuned_undoretention,
       ssolderrcnt,
       nospaceerrcnt
FROM v$undostat
ORDER BY begin_time DESC
FETCH FIRST 24 ROWS ONLY;

NOSPACEERRCNT が増えている時間帯は、UNDO不足が実際に発生しています。MAXQUERYLEN が長い場合は、長時間クエリのために古いUNDOを保持する必要があり、DML側と競合しやすくなります。

原因1:UNDO表領域が単純に小さい

データ量や更新量に対してUNDO表領域が小さい場合、解決策はサイズを増やすことです。ただし、現在サイズだけでなくピーク時の更新量、長時間クエリ、バッチ時間帯を考慮して設計します。

確認するものUNDO表領域サイズ、AUTOEXTEND上限、ピーク時の V$UNDOSTAT.UNDOBLKS、ORA-30036発生時間帯です。
短期対処データファイル追加、既存ファイル拡張、MAXSIZE見直しを行います。
恒久対策日次・月次バッチ、Data Pump、洗い替え処理のピークUNDO量をもとに、余裕を持ったサイズへ変更します。

原因2:長時間トランザクションがUNDOを握っている

COMMITされていない大きなトランザクションがあると、そのUNDOはACTIVEのままです。ほかの処理がUNDOを使おうとしても再利用できず、ORA-30036につながります。

long-transaction-check.sql
SELECT s.sid,
       s.serial#,
       s.username,
       s.status,
       s.module,
       s.sql_id,
       t.start_time,
       t.used_ublk,
       t.used_urec
FROM v$transaction t
JOIN v$session s
  ON s.taddr = t.addr
ORDER BY t.start_time;

対象が不要なセッションであれば、業務影響を確認して終了を検討します。ただし、KILLするとロールバックが走り、その間もUNDOやI/Oを使います。本当に止めてよい処理かを確認してから実行します。

kill-session-example.sql
ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE;

原因3:大量DMLのCOMMIT粒度が大きすぎる

一度に大量のDELETEやUPDATEを行い、最後に1回だけCOMMITする処理はUNDOを大きく消費します。業務的に分割できるなら、キー範囲や日付範囲でチャンク化し、適切な単位でCOMMITします。

chunk-delete-pattern.sql
DECLARE
  l_rows PLS_INTEGER;
BEGIN
  LOOP
    DELETE FROM access_logs
    WHERE log_date < ADD_MONTHS(TRUNC(SYSDATE), -12)
      AND ROWNUM <= 10000;

    l_rows := SQL%ROWCOUNT;
    COMMIT;

    EXIT WHEN l_rows = 0;
  END LOOP;
END;
/

ただし、COMMITを細かくしすぎると、業務整合性や再実行設計が難しくなります。チャンク処理は、再開位置、失敗時の扱い、途中結果の一貫性まで決めます。大規模バッチの並列化は DBMS_PARALLEL_EXECUTEによる大規模バッチの並列化戦略 も関連します。

原因4:UNDO_RETENTIONが高すぎる・RETENTION GUARANTEEが有効

UNDO_RETENTION は、古いUNDOをどれくらい保持しようとするかの設定です。長時間クエリやFlashback用途には重要ですが、値が大きすぎるとUNDO表領域の圧迫につながります。さらに RETENTION GUARANTEE が有効なUNDO表領域では、未期限切れUNDOをより強く保持するため、DMLがORA-30036で失敗しやすくなります。

undo-retention-check.sql
SHOW PARAMETER undo_retention;

SELECT tablespace_name,
       retention
FROM dba_tablespaces
WHERE contents = 'UNDO';

SELECT begin_time,
       tuned_undoretention,
       maxquerylen,
       nospaceerrcnt
FROM v$undostat
ORDER BY begin_time DESC
FETCH FIRST 12 ROWS ONLY;

短期的に UNDO_RETENTION を下げると領域圧迫が緩むことがありますが、ORA-01555を増やす可能性があります。本番では、単に値を下げるのではなく、長時間クエリの必要性、Flashback要件、UNDO表領域サイズをセットで見直します。

RETENTION GUARANTEEを確認・変更する

RETENTION GUARANTEE が有効なUNDO表領域では、未期限切れUNDOを守るため、DMLが領域不足で失敗しやすくなります。長時間クエリやFlashbackを守るための設定なので、解除する場合は業務要件を確認します。

retention-guarantee-check.sql
SELECT tablespace_name,
       retention
FROM dba_tablespaces
WHERE contents = 'UNDO';

-- 解除する場合。長時間クエリやFlashback要件を確認してから実行する
ALTER TABLESPACE UNDOTBS1 RETENTION NOGUARANTEE;

-- 保証を有効にする場合。十分なUNDO容量を確保してから使う
ALTER TABLESPACE UNDOTBS1 RETENTION GUARANTEE;

原因5:Data Pumpや一括更新が集中している

Data Pumpのインポート、移行バッチ、洗い替え、月次処理などが重なると、UNDOのピークが通常時と大きく変わります。定常監視では問題がなくても、特定の時間帯だけORA-30036が出るなら、ジョブの重なりを確認します。

ジョブをずらす大量DML、Data Pump、インデックス再作成、集計バッチが同時に走っていないか確認します。
処理を分割するDELETE/UPDATEを日付範囲や主キー範囲で分け、ピークUNDOを下げます。
一時的にUNDOを増やす移行や大型メンテナンス前だけUNDO表領域を拡張し、作業後に通常サイズへ戻す計画を立てます。

Data Pump全体の使い方は Oracle Data Pump完全ガイド、ダイレクトパスインサートは ダイレクト・パス・インサート完全ガイド も参考になります。

ORA-01555との違い

ORA-30036ORA-01555 はどちらもUNDOに関係しますが、意味が違います。

ORA-30036更新処理が必要なUNDO領域を確保できない状態です。主にDML側が止まります。
ORA-01555長時間クエリが必要とする古いUNDOが上書きされ、読み取り一貫性を維持できない状態です。主にSELECT側が失敗します。
対策の方向ORA-30036は領域追加やDML分割、ORA-01555はUNDO保持、長時間クエリ短縮、fetch across commit回避が中心です。

片方だけを見て設定を変えると、もう片方が悪化することがあります。たとえばUNDO_RETENTIONを短くするとORA-30036は減る可能性がありますが、ORA-01555は増える可能性があります。

再発防止の監視SQL

ORA-30036は、発生してから対応すると業務影響が大きくなります。UNDO表領域の使用状況、ACTIVE領域、NOSPACEERRCNT、長時間トランザクションを定期的に見ます。

undo-monitoring.sql
-- UNDO表領域の状態
SELECT tablespace_name,
       status,
       ROUND(SUM(bytes) / 1024 / 1024) AS mb
FROM dba_undo_extents
GROUP BY tablespace_name, status
ORDER BY tablespace_name, status;

-- 直近のUNDO不足発生回数
SELECT begin_time,
       end_time,
       undoblks,
       txncount,
       tuned_undoretention,
       nospaceerrcnt,
       ssolderrcnt
FROM v$undostat
ORDER BY begin_time DESC
FETCH FIRST 12 ROWS ONLY;

-- UNDOを多く使うトランザクション
SELECT s.sid,
       s.serial#,
       s.username,
       s.module,
       t.start_time,
       t.used_ublk,
       t.used_urec
FROM v$transaction t
JOIN v$session s
  ON s.taddr = t.addr
ORDER BY t.used_ublk DESC;

監視では、使用率だけでなく NOSPACEERRCNT と長時間トランザクションを見るのがポイントです。使用率が低く見えても、特定処理の瞬間的なピークでORA-30036が出ることがあります。

本番対応フロー

  • エラーメッセージからUNDO表領域名を確認する
  • ディスク空き容量、ASM空き容量、データファイル上限を確認する
  • 必要ならUNDO表領域にデータファイルを追加する
  • DBA_UNDO_EXTENTS でACTIVE/UNEXPIRED/EXPIREDの割合を見る
  • V$TRANSACTION でUNDOを多く使うセッションを特定する
  • V$UNDOSTAT でNOSPACEERRCNTとピーク時間帯を確認する
  • 長時間トランザクション、大量DML、ジョブ重複を調べる
  • COMMIT粒度、チャンク化、ジョブ時間帯、UNDO表領域サイズを見直す
  • UNDO_RETENTIONとRETENTION GUARANTEEの設定を確認する
  • 対応後にORA-01555が増えていないかも確認する

やってはいけない対応

いきなりセッションをKILLするロールバックに時間がかかり、さらにUNDOやI/Oを消費することがあります。業務影響を確認してから実行します。
UNDO_RETENTIONを極端に下げるORA-01555やFlashback失敗につながる可能性があります。
AUTOEXTENDを無制限にするOSやASMの空き領域を使い切り、より大きな障害になります。
原因を見ずに毎回容量追加する長時間トランザクションやバッチ設計の問題を放置すると、増やした領域もすぐ使い切ります。

まとめ

ORA-30036は、UNDO表領域でUNDOセグメントを拡張できないときに発生します。本番で発生したら、まずUNDO表領域への領域追加やAUTOEXTEND設定で止血し、その後にACTIVEな長時間トランザクション、UNDO_RETENTION、RETENTION GUARANTEE、大量DML、ジョブ重複を調べます。

再発防止では、UNDO表領域のサイズを増やすだけでなく、COMMIT粒度、チャンク処理、ピーク時間帯のジョブ設計、V$UNDOSTAT の監視をセットで整えることが重要です。ORA-01555やTEMP不足とは対策が異なるため、エラーコードごとに正しく切り分けましょう。