【Oracle】ORA-08103の原因と解決方法|object no longer exists・実行中に表が消えた時の対処

【Oracle】ORA-08103の原因と解決方法|object no longer exists・実行中に表が消えた時の対処 Oracle

ORA-08103: object no longer exists は、OracleでSQL実行中に参照していたオブジェクトが、実行開始後に削除・切り替え・再作成された時に発生するエラーです。長いSELECT、バッチ処理、パーティションメンテナンス、TRUNCATE、DROP、EXCHANGE PARTITION、オンライン再定義、リカバリ直後などで見かけます。

Oracle公式のエラー説明では、操作開始後に別ユーザーによってオブジェクトが削除された、または不完全リカバリで削除中の時点へ戻ったことが原因として説明されています。つまり、単に「表名を間違えた」というより、SQLが見ていたオブジェクトの実体が途中でなくなったと考えるのが近いです。DDL操作全般は Oracle ALTER TABLE完全ガイド、パーティション運用は Oracleパーティションテーブル完全ガイド もあわせて確認してください。

この記事で整理すること

  • ORA-08103が発生する典型パターン
  • DROP、TRUNCATE、EXCHANGE PARTITION、再作成との関係
  • 対象オブジェクトの存在確認SQL
  • DDLを実行したユーザーを監査ログ・アプリログから追う方法
  • 再実行してよいケース、リカバリが必要なケース
  • パーティションメンテナンス時の再発防止
  • ORA-00054、ORA-04021、ORA-01502との違い
スポンサーリンク

重複確認結果

本番DBで ORA-08103object no longer exists を検索しましたが、ORA-08103単独記事は見つかりませんでした。既存にはDDLロック、パーティション、Flashback、RMAN、Data Pumpの記事があるため、この記事は実行中にオブジェクトが変わった時のエラー対処記事として作成しています。

最初に結論:再実行前にDDL履歴を確認する

ORA-08103は、再実行すれば通ることもあります。しかし、本番ではすぐ再実行する前に、対象表やパーティションに対してDROP、TRUNCATE、EXCHANGE、MOVE、RENAME、再作成、オンライン再定義が走っていないか確認します。

単発SELECTで出た実行中に対象表・パーティションがTRUNCATEやEXCHANGEされた可能性があります。再実行前にメンテナンス履歴を確認します。
バッチ中に出た同時刻のDDLジョブ、パーティション切替、ステージング表のDROP/TRUNCATEを確認します。
リカバリ後に出た不完全リカバリやFlashbackでオブジェクトの状態が戻っていないか確認します。
繰り返し出るアプリやジョブが参照中の表を入れ替える設計になっていないか見直します。

DDLロック待ちの代表例は ORA-00054完全ガイド、DDLやコンパイルの待機は ORA-04021の原因と解決方法 が関連します。

原因別の判断フロー

ORA-08103が出たら、まず「参照中に何が変わったのか」を切り分けます。同じエラーでも、TRUNCATE、DROP、パーティション入れ替え、リカバリでは対応が変わります。

LAST_DDL_TIMEが直近対象表やパーティションにDDLが走った可能性が高いです。監査ログ、ジョブ履歴、デプロイログを確認します。
DATA_OBJECT_IDが変わったTRUNCATE、MOVE、EXCHANGE PARTITION、再作成などで実体が変わった可能性があります。
対象表が消えているDROPやPURGEを疑います。リサイクルビン、Flashback、RMAN復元可否を確認します。
長時間SELECTだけが失敗参照中にパーティションメンテナンスやTRUNCATEが重なった可能性があります。処理時間帯を分けます。

ORA-08103が起きる典型パターン

ORA-08103のポイントは、SQL実行開始時にはオブジェクトを見ていたのに、処理途中でその実体がなくなることです。長時間SELECTやバッチ処理ほど発生しやすくなります。

SELECT中にTRUNCATEされる

truncate-during-select.sql
-- セッションA: 長いSELECTを実行中
SELECT *
FROM sales_work
WHERE sales_date >= DATE '2026-01-01';

-- セッションB: 同じ表をTRUNCATE
TRUNCATE TABLE sales_work;

-- セッションA側で ORA-08103 が発生することがある

参照中にパーティションをEXCHANGEする

exchange-partition-during-query.sql
-- セッションA: 特定パーティションを含む集計中
SELECT SUM(amount)
FROM sales
WHERE sales_date >= DATE '2026-05-01'
  AND sales_date <  DATE '2026-06-01';

-- セッションB: 対象パーティションを入れ替え
ALTER TABLE sales
  EXCHANGE PARTITION p202605
  WITH TABLE sales_202605_new
  WITHOUT VALIDATION;

DROPして同名で作り直す

drop-recreate-object.sql
DROP TABLE report_work PURGE;

CREATE TABLE report_work AS
SELECT *
FROM report_source;

-- 名前は同じでも、内部的には別オブジェクトになる

テーブル操作の基本は Oracle INSERT・UPDATE・DELETE完全ガイド、DROP文の生成や動的実行は DROP TABLE文を一括生成する方法 が関連します。

まず対象オブジェクトの状態を確認する

エラーに出ているSQLがどの表・パーティションを参照していたかを確認し、現在そのオブジェクトが存在するか、作成時刻や最終DDL時刻が変わっていないかを見ます。

object-status-check.sql
SELECT owner,
       object_name,
       object_type,
       object_id,
       data_object_id,
       status,
       created,
       last_ddl_time
FROM all_objects
WHERE owner = 'APP'
  AND object_name IN ('SALES_WORK', 'SALES')
ORDER BY owner, object_name, object_type;

OBJECT_IDDATA_OBJECT_ID は、オブジェクトの実体確認で重要です。TRUNCATEやMOVE、パーティション操作で DATA_OBJECT_ID が変わることがあります。

DATA_OBJECT_IDの変化を見る例

名前が同じ表でも、TRUNCATEや再作成で実体が変わることがあります。障害調査では、エラー発生前後で DATA_OBJECT_IDLAST_DDL_TIME が変わっていないかを見ます。

data-object-id-compare.sql
-- DDL前に控えておく、または監査ログと突き合わせる
SELECT object_name,
       object_id,
       data_object_id,
       last_ddl_time
FROM user_objects
WHERE object_name = 'SALES_WORK'
  AND object_type = 'TABLE';

TRUNCATE TABLE sales_work;

-- TRUNCATE後はDATA_OBJECT_IDやLAST_DDL_TIMEが変わることがある
SELECT object_name,
       object_id,
       data_object_id,
       last_ddl_time
FROM user_objects
WHERE object_name = 'SALES_WORK'
  AND object_type = 'TABLE';

パーティション単位の状態を確認する

ORA-08103は表全体だけでなく、参照中のパーティションが入れ替わった場合にも起きます。パーティション表では、表だけでなくパーティションの状態も確認します。

partition-object-check.sql
SELECT table_name,
       partition_name,
       partition_position,
       tablespace_name,
       num_rows,
       last_analyzed
FROM user_tab_partitions
WHERE table_name = 'SALES'
ORDER BY partition_position;

SELECT object_name,
       subobject_name,
       object_type,
       object_id,
       data_object_id,
       last_ddl_time
FROM user_objects
WHERE object_name = 'SALES'
ORDER BY subobject_name NULLS FIRST;

月次パーティション運用では、パーティション追加やEXCHANGE、TRUNCATE PARTITION、DROP PARTITIONの時間帯を、参照バッチと重ねないことが重要です。パーティションキー不足のエラーは ORA-14400の原因と解決方法 も関連します。

DDLを実行した履歴を探す

ORA-08103の調査では、誰がいつDDLを実行したかが重要です。本番では統合監査、アプリケーションログ、ジョブ履歴、デプロイログ、DBA操作ログを突き合わせます。

unified-audit-ddl-check.sql
SELECT event_timestamp,
       dbusername,
       action_name,
       object_schema,
       object_name,
       sql_text
FROM unified_audit_trail
WHERE event_timestamp >= SYSTIMESTAMP - INTERVAL '1' DAY
  AND action_name IN (
    'DROP TABLE',
    'TRUNCATE TABLE',
    'ALTER TABLE',
    'CREATE TABLE',
    'RENAME'
  )
ORDER BY event_timestamp DESC;

統合監査の設定や見方は Oracle統合監査完全ガイド が関連します。監査が未設定なら、今後の再発防止としてDDL監査を検討します。

監査が未設定だった場合の代替調査

監査ログがない場合でも、AWRのSQL履歴、スケジューラ履歴、デプロイログ、アプリログから手がかりを拾えることがあります。ただし、必ず残っているとは限らないため、再発防止としてDDL監査を有効化するのが本筋です。

fallback-ddl-investigation.sql
-- AWRに残っているDDLらしきSQLを探す
SELECT sql_id,
       parsing_schema_name,
       sql_text
FROM dba_hist_sqltext
WHERE UPPER(sql_text) LIKE 'TRUNCATE TABLE%'
   OR UPPER(sql_text) LIKE 'DROP TABLE%'
   OR UPPER(sql_text) LIKE 'ALTER TABLE%'
ORDER BY sql_id;

-- DBMS_SCHEDULERの実行履歴を見る
SELECT log_date,
       owner,
       job_name,
       status,
       additional_info
FROM dba_scheduler_job_run_details
WHERE log_date >= SYSTIMESTAMP - INTERVAL '1' DAY
ORDER BY log_date DESC;

リサイクルビンとFlashbackを確認する

DROP TABLEが原因の場合、リサイクルビンに残っていればFlashback Dropで戻せる可能性があります。ただし、PURGEされている場合やTRUNCATEの場合はリサイクルビンでは戻せません。

recyclebin-check.sql
SELECT object_name,
       original_name,
       type,
       droptime
FROM user_recyclebin
WHERE original_name IN ('SALES_WORK', 'REPORT_WORK')
ORDER BY droptime DESC;

-- 戻せる場合
FLASHBACK TABLE report_work TO BEFORE DROP;

Flashback Dropやリサイクルビンは リサイクルビン・FLASHBACK DROP完全ガイド、Flashback全体は Oracleフラッシュバック完全ガイド を確認してください。

再実行してよいケース・いけないケース

ORA-08103は、原因が一時的なDDL競合であれば再実行で通ることがあります。ただし、再実行してよいかは、SQLの種類と業務処理の冪等性によります。

再実行しやすいSELECTだけのレポート、読み取り専用の集計、途中結果を保存しない処理です。
慎重に再実行するINSERT SELECT、MERGE、DELETE、外部連携、メール送信など、副作用がある処理です。
リカバリを優先する表がDROPされた、TRUNCATEされた、誤ったEXCHANGEが行われた、データが失われた可能性がある場合です。
原因確認が必要同じ時間帯にメンテナンスジョブやデプロイが走っている場合、再実行しても再発します。

トランザクションと再実行設計は Oracleトランザクション完全ガイド が関連します。

パーティションメンテナンス時の再発防止

EXCHANGE PARTITION、DROP PARTITION、TRUNCATE PARTITION、MOVE PARTITIONは、参照中のSQLとぶつかるとORA-08103の原因になります。参照バッチとメンテナンスバッチの時間帯を分け、必要ならロック待ちや排他制御を明示します。

maintenance-window-check.sql
-- メンテナンス前に対象表を参照しているセッションを確認
SELECT s.sid,
       s.serial#,
       s.username,
       s.module,
       s.action,
       s.sql_id,
       q.sql_text
FROM v$session s
LEFT JOIN v$sql q
  ON q.sql_id = s.sql_id
WHERE q.sql_text LIKE '%SALES%'
ORDER BY s.logon_time;

パーティションメンテナンス後にインデックスがUNUSABLEになる場合もあります。その場合は ORA-01502の原因と解決方法 を確認してください。

オンライン再定義・表入れ替え設計の注意点

大きな表を再作成して入れ替える設計では、同名オブジェクトをDROP/CREATEするより、DBMS_REDEFINITIONやビュー切り替え、シノニム切り替えなどを検討します。ただし、どの方法でも参照中SQLとの整合性、ロック、切り替えタイミングを設計する必要があります。

avoid-drop-recreate.sql
-- 避けたい例: 参照中の可能性がある本表をDROPして同名で作り直す
DROP TABLE sales_summary PURGE;

CREATE TABLE sales_summary AS
SELECT customer_id,
       SUM(amount) AS total_amount
FROM sales
GROUP BY customer_id;

-- 代替案: ステージング表を作成し、切り替えタイミングを短くする
CREATE TABLE sales_summary_new AS
SELECT customer_id,
       SUM(amount) AS total_amount
FROM sales
GROUP BY customer_id;

オンライン再定義は DBMS_REDEFINITION完全ガイド、Data Pumpを使った移行は Data Pump完全ガイド が関連します。

バックアップ・リカバリが必要なケース

誤DROP、誤TRUNCATE、誤EXCHANGEでデータが失われた可能性がある場合は、単純な再実行ではなくリカバリを検討します。Flashbackで戻せるか、RMANで復元が必要か、業務影響を確認します。

recovery-decision.sql
-- DROPならリサイクルビン確認
SELECT original_name,
       object_name,
       droptime
FROM user_recyclebin
WHERE original_name = 'SALES_WORK';

-- Flashback Queryで過去状態を参照できるか確認
SELECT COUNT(*)
FROM sales_work AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE);

RMANの基本は Oracle RMAN完全ガイド、変更履歴の追跡は Flashback Version Query・Transaction Query完全ガイド が役立ちます。

避けたい対応

原因を見ずに再実行するSELECTだけなら通ることもありますが、DMLや外部連携を含む処理では二重実行の危険があります。
参照中の表をTRUNCATEする高速ですが、実行中SQLに影響します。参照バッチと時間帯を分けます。
DROPして同名再作成する名前が同じでも内部的には別オブジェクトです。参照中SQLや依存オブジェクトに影響します。
監査なしでDDLを許可する誰がいつ消したか追えないと、再発防止ができません。

本番対応チェックリスト

  • エラーが出たSQLと対象表・パーティションを特定した
  • ALL_OBJECTSLAST_DDL_TIMEDATA_OBJECT_ID を確認した
  • 対象時間帯のDDL監査ログ、デプロイログ、ジョブ履歴を確認した
  • TRUNCATE、DROP、EXCHANGE PARTITION、MOVE、RENAME、再作成が走っていないか確認した
  • パーティション表では対象パーティションの状態も確認した
  • 再実行してよい処理か、副作用や二重実行リスクを確認した
  • DROPが原因ならリサイクルビンやFlashbackで戻せるか確認した
  • データ損失が疑われる場合、RMANやFlashbackの復旧方針を確認した
  • DDL監査、メンテナンス時間帯、排他制御を再発防止策に入れた
  • 参照バッチとパーティションメンテナンスが重ならないようにした

まとめ

ORA-08103は、SQL実行中に参照していたオブジェクトが削除・TRUNCATE・EXCHANGE・再作成などで変わった時に発生します。単に表が存在しないというより、実行中に見ていたオブジェクトの実体がなくなった、という切り分けが重要です。

本番では、対象オブジェクトの DATA_OBJECT_IDLAST_DDL_TIME、DDL監査ログ、パーティション操作履歴を確認してから再実行を判断します。再発防止には、参照バッチとDDLメンテナンスの時間帯分離、DDL監査、パーティション運用の排他制御が効きます。