【完全ガイド】ORA-04061: existing state of … has been invalidated の原因と解決方法|ORA-04068 との違い・グローバル状態・EBR 徹底解説
- 作成日 2026.08.24
- Oracle Database
Oracle 開発者・DBA が本番運用中のパッケージ更新で頻繁に遭遇するエラー:
ORA-04061: existing state of package body "APPS.PO_REQAPPROVAL_INIT1" has been invalidated
ORA-04065: not executed, altered or dropped package body "APPS.PO_REQAPPROVAL_INIT1"
ORA-06508: PL/SQL: could not find program unit being called: "APPS.PO_REQAPPROVAL_INIT1"
**「既存状態が無効化された」**というシンプルなメッセージ。Oracle のパッケージ状態管理における重要なエラーです:
- セッションが保持していたパッケージ状態の無効化
- パッケージ変更中のセッションで発生
- Oracle EBS Workflowで頻発
- アプリケーションの動作停止
- 24時間運用の障害
このエラーの本質は、セッションのパッケージ状態と現在のパッケージ定義が不整合:
1. セッション A がパッケージ P を実行
2. P のグローバル変数 / 定数 / カーソル状態を保持
3. 別セッション B が P を再コンパイル/変更
4. セッション A が再度 P を呼び出し
5. → 保持状態と新しい P が不整合
6. → ORA-04061 発生
- 1. 結論:再実行 or グローバル状態排除
- 2. Oracle パッケージの状態管理
- 3. 【原因①】パッケージ再コンパイル中(最頻出)
- 4. 【原因②】Oracle E-Business Suite Workflow
- 5. 【原因③】グローバル状態を持つパッケージ(根本原因)
- 6. 【原因④】Rails / Django マイグレーション中
- 7. 【原因⑤】CI/CD デプロイ中
- 8. 【原因⑥】Oracle datapatch 中
- 9. 【原因⑦】パッケージ内定数変更
- 10. 【原因⑧】型変更(Object Type)
- 11. 【原因⑨】Java Callable Statement
- 12. 【原因⑩】PL/SQL 呼び出し内
- 13. 診断ツール完全リファレンス
- 14. 7つの解決策 完全リファレンス
- 15. Rails / Java / Python 対応
- 16. 実践シナリオ
- 17. トラブルシューティング
- 18. よくある質問(FAQ)
- 19. 参考リンク
- 20. まとめ
ORA-04061 vs ORA-04068 の決定的違い
極めて混同しやすい姉妹エラー:
ORA-04061: existing state has been INVALIDATED
→ 状態が無効化された
→ コンパイル時に検出
→ 「まだ状態は残っている、しかし使えない」
ORA-04068: existing state has been DISCARDED
→ 状態が破棄された
→ 実行時に発生
→ 「状態自体が消えた」
両者は通常セットで発生、原因は同じ(パッケージ変更)。
現場で最も典型的なのは、Oracle E-Business Suite (EBS):
[WF_ERROR] ERROR_MESSAGE=3835:
Error '-20002 - ORA-20002: 2018: Unable to generate the notification XML.
ORA-04061: existing state of package body "APPS.PO_WF_PO_NOTIFICATION" has been invalidated
シナリオ:
1. EBS Workflow が動作中
2. APPS.PO_WF_PO_NOTIFICATION パッケージ更新
3. Workflow セッションが再アクセス
4. → ORA-04061 → PO 承認通知メール失敗
多くの日本語記事が「再実行せよ」で終わりますが、実務では:
ORA-04061vsORA-04068の厳密な違い- 併発エラー4種(
ORA-04065, ORA-04063, ORA-06508, ORA-06512) - グローバル状態を持つパッケージの根本問題
PRAGMA SERIALLY_REUSABLEによる回避- Edition-Based Redefinition (EBR) の活用
DBMS_SESSION.RESET_PACKAGEの使い所と限界- Rails ActiveRecord の接続プールリセット
- Oracle datapatch 中の発生(19.10 アップグレード等)
- Oracle EBS AutoConfig / adadmin での対処
- Oracle 26ai の
SESSION_EXIT_ON_PACKAGE_STATE_ERROR新機能
さらに、根本原因を理解することが重要です:
グローバル状態を持つパッケージの問題:
PACKAGE state = セッションごとに独立
→ セッションで保持したまま、パッケージ再コンパイル
→ 状態と定義の不整合
→ ORA-04061
解決方針:
1. グローバル状態を持たないパッケージ設計
2. PRAGMA SERIALLY_REUSABLE で毎回リセット
3. Functions を使い状態を持たない
4. EBR で古い定義を維持
本記事では、ORA-04061: existing state of has been invalidated の完全な原因と解決方法を、リファレンスとして実用的に整理します。ORA-04068 との違い、10大発生パターン、7つの解決策、EBR、Rails/Java/Python 対応、実践シナリオ、FAQまで完全網羅。この1本で ORA-04061 に冷静に対処できるようになります。
結論:再実行 or グローバル状態排除
時間がない方向けに、最速の対処を先に示します。
エラーメッセージの読み方
ORA-04061: existing state of package body "SCHEMA.PACKAGE" has been invalidated
↑
無効化されたオブジェクト
= セッションが保持していた状態と、変更されたパッケージ定義が不整合
最速の対処
即時対処: 再実行(同じ呼び出しをリトライ)
→ Oracle が状態を自動的に再初期化
→ 通常成功
根本対処:
1. パッケージからグローバル状態を除去
2. PRAGMA SERIALLY_REUSABLE 追加
3. Functions で状態を持たない設計
併発エラー4種
| エラー | 意味 |
|---|---|
| ORA-04061 | 状態が無効化された |
| ORA-04065 | パッケージが変更/削除された |
| ORA-06508 | プログラムユニット発見不可 |
| ORA-06512 | 発生位置(スタックトレース) |
通常セットで発生。
7つの解決策
| # | 手法 | 使う場面 |
|---|---|---|
| ① | 再実行 | 一時的対処 |
| ② | グローバル状態除去 | 根本対処 |
| ③ | PRAGMA SERIALLY_REUSABLE | パッケージ設計 |
| ④ | Functions 使用 | 状態レス化 |
| ⑤ | Edition-Based Redefinition | 高度な回避 |
| ⑥ | Rails 接続プールリセット | Rails 対応 |
| ⑦ | SESSION_EXIT_ON_PACKAGE_STATE_ERROR | 26ai 新機能 |
ORA-04061 vs ORA-04068
ORA-04061: INVALIDATED(無効化)
- コンパイル時に検出
- 状態はまだあるが使えない
ORA-04068: DISCARDED(破棄)
- 実行時に発生
- 状態自体が消えた
通常両方セットで発生。
詳細は以下で解説します。
Oracle パッケージの状態管理
パッケージ状態とは
パッケージは以下を持つ:
CREATE OR REPLACE PACKAGE my_pkg IS
g_counter NUMBER := 0; -- グローバル変数(状態)
g_config VARCHAR2(100); -- グローバル変数
PROCEDURE proc_a;
END my_pkg;
/
各セッションが独自の状態を保持:
セッション A: g_counter = 5
セッション B: g_counter = 10
セッション C: g_counter = 3
状態の永続性
通常のパッケージ:
- セッション終了まで状態保持
- 同じセッションからの再呼び出しで同じ状態
PRAGMA SERIALLY_REUSABLE:
- 各呼び出し毎に状態リセット
- サーバー再利用性向上
状態の無効化契機
1. パッケージ本体 (BODY) の変更/再コンパイル
2. パッケージ仕様 (SPEC) の変更/再コンパイル
3. 依存オブジェクトの変更
4. DBMS_SESSION.RESET_PACKAGE 呼び出し
→ セッションが次にパッケージ呼び出し
→ ORA-04061 or ORA-04068
【原因①】パッケージ再コンパイル中(最頻出)
シナリオ
セッション A: my_pkg 使用中(状態保持)
セッション B (DBA): ALTER PACKAGE my_pkg COMPILE BODY;
セッション A: 再度 my_pkg 呼び出し
→ ORA-04061 発生
対処
A. 再実行(Oracle 自動回復):
BEGIN
my_pkg.proc_a;
END;
/
-- 初回: ORA-04061
-- 再度実行: 通常成功(状態が再初期化される)
B. アプリで自動リトライ:
def call_proc
ActiveRecord::Base.connection.execute("BEGIN my_pkg.proc_a; END;")
rescue ActiveRecord::StatementInvalid => e
if e.message.include?("ORA-04061") && (retries ||= 0) < 3
retries += 1
retry
end
raise
end
【原因②】Oracle E-Business Suite Workflow
症状(現場頻発)
ERROR: Action Required: Error3240: Error '-4061'
ORA-04061: existing state of package body "APPS.PO_WF_PO_NOTIFICATION"
has been invalidated
ORA-04065: not executed, altered or dropped package body
ORA-06508: PL/SQL: could not find program unit being called
PO 承認、Absence 承認、Appraisal 承認の通知メール失敗。
対処(Oracle 公式手順)
A. Notification Mailer 再起動 + Shared Pool フラッシュ:
-- SYSDBA で
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
B. Concurrent Manager / Apache 停止 → adadmin で APPS 再コンパイル:
# EBS 環境で
$COMMON_TOP/admin/scripts/$SID/adstpall.sh apps/apps
# adadmin 起動
adadmin
# Recompile APPS Schema オプション実行
# 再起動
$COMMON_TOP/admin/scripts/$SID/adstrtal.sh apps/apps
C. 定期的な INVALID オブジェクト再コンパイル:
BEGIN
UTL_RECOMP.recomp_parallel(4, 'APPS');
END;
/
INVALID オブジェクト関連は PLS-00905: object is invalid の記事、ORA-04068: existing state of packages の記事も参照してください。
【原因③】グローバル状態を持つパッケージ(根本原因)
問題のコード
CREATE OR REPLACE PACKAGE sith_manager AS
gc_default_name CONSTANT VARCHAR2(200) := 'Darth Ora';
PROCEDURE add_sith(i_name VARCHAR2);
END sith_manager;
/
CREATE OR REPLACE PACKAGE BODY sith_manager AS
PROCEDURE add_sith(i_name VARCHAR2) IS
BEGIN
INSERT INTO sith (name)
VALUES (NVL(i_name, gc_default_name));
END;
END sith_manager;
/
問題: gc_default_name が定数でもパッケージ状態を持つと Oracle が判定。
解決A: PRAGMA SERIALLY_REUSABLE
CREATE OR REPLACE PACKAGE sith_manager AS
PRAGMA SERIALLY_REUSABLE; -- ← 追加
gc_default_name CONSTANT VARCHAR2(200) := 'Darth Ora';
PROCEDURE add_sith(i_name VARCHAR2);
END sith_manager;
/
CREATE OR REPLACE PACKAGE BODY sith_manager AS
PRAGMA SERIALLY_REUSABLE; -- ← 本体にも
...
END;
/
効果: 各呼び出し毎にリセット、状態問題回避。
解決B: 状態のない Functions
-- 状態を持たない設計
CREATE OR REPLACE FUNCTION get_default_name RETURN VARCHAR2 IS
BEGIN
RETURN 'Darth Ora';
END;
/
-- パッケージ本体
CREATE OR REPLACE PACKAGE BODY sith_manager AS
PROCEDURE add_sith(i_name VARCHAR2) IS
BEGIN
INSERT INTO sith (name)
VALUES (NVL(i_name, get_default_name));
END;
END sith_manager;
/
【原因④】Rails / Django マイグレーション中
シナリオ
# Rails マイグレーション実行中
class CompilePackages < ActiveRecord::Migration[8.0]
def up
execute "ALTER PACKAGE my_pkg COMPILE BODY"
end
end
# 一方、Web アプリが my_pkg 使用中
# → ORA-04061 発生
解決
A. マイグレーション後の接続プールリセット:
class CompilePackages < ActiveRecord::Migration[8.0]
def up
execute "ALTER PACKAGE my_pkg COMPILE BODY"
# 接続プールを全リセット(全セッションで状態リセット)
ActiveRecord::Base.connection_pool.disconnect!
end
end
B. デプロイ順序管理(Kamal 等):
# 1. 一時的にアプリ停止
kamal app stop
# 2. マイグレーション
kamal migrate
# 3. アプリ再起動
kamal app start
Rails 8 系の詳細は Rails 8 アップグレードガイドの記事、rails db:migrate 使い方の記事、Kamal 2 デプロイの記事も参照してください。
【原因⑤】CI/CD デプロイ中
シナリオ
# デプロイ中
- name: Deploy PL/SQL
run: |
sqlplus $DB_USER/$DB_PW <<EOF
@deploy_packages.sql
EOF
# アプリは継続稼働 → ORA-04061 頻発
解決
A. デプロイ時にアプリ一時停止(推奨)。 B. アプリでリトライロジック。 C. Edition-Based Redefinition 使用(後述)。
【原因⑥】Oracle datapatch 中
症状(19c → 19.10 パッチ適用中)
Patch 31281355 apply: WITH ERRORS
- ORA-04068: existing state of packages has been discarded
- ORA-04061: existing state of package body "SYS.DBMS_AQADM_SYS" has been invalidated
- ORA-04065: not executed, altered or dropped package body "SYS.DBMS_AQADM_SYS"
- ORA-06508: PL/SQL: could not find program unit being called
- ORA-06512: at "SYS.DBMS_AQADM", line 1090
Oracle 内部の rdbms/admin/catsnmp.sql 実行時。
解決(Oracle 公式)
A. datapatch 前に隠しパラメータ設定:
ALTER SYSTEM SET "_srvntfn_job_deq_timeout" = 0 SCOPE=SPFILE;
-- 再起動
B. パッチ適用後リセット:
ALTER SYSTEM RESET "_srvntfn_job_deq_timeout" SCOPE=BOTH;
C. DB 再起動。
Unpublished BUG 32174571 として Oracle が認識。
【原因⑦】パッケージ内定数変更
シナリオ
-- 変更前
CREATE PACKAGE cfg IS
MAX_RETRY CONSTANT NUMBER := 3;
END;
/
-- 変更後
CREATE OR REPLACE PACKAGE cfg IS
MAX_RETRY CONSTANT NUMBER := 5; -- 変更
END;
/
-- 使用中セッション → ORA-04061
解決
A. アプリ再起動(接続プールリセット)。 B. DBMS_SESSION.RESET_PACKAGE :
BEGIN
DBMS_SESSION.RESET_PACKAGE;
END;
/
-- 現セッションの全パッケージ状態リセット
⚠️ 副作用大、慎重に。
【原因⑧】型変更(Object Type)
シナリオ
-- Object Type 変更
ALTER TYPE addr_t ADD ATTRIBUTE (country VARCHAR2(50)) CASCADE;
-- 使用中セッション → ORA-04061 の可能性
解決
A. 使用中セッション終了 → 再接続。 B. Edition-Based Redefinition(後述)。
【原因⑨】Java Callable Statement
シナリオ
// Java アプリで長時間セッション
CallableStatement cs = conn.prepareCall("{call my_pkg.proc_a}");
cs.execute();
// 別セッションで my_pkg 更新
// → 次回 cs.execute() で ORA-04061
解決
try {
cs.execute();
} catch (SQLException e) {
if (e.getErrorCode() == 4061) {
// 接続再取得
conn.close();
conn = ds.getConnection();
cs = conn.prepareCall("{call my_pkg.proc_a}");
cs.execute(); // リトライ
}
}
【原因⑩】PL/SQL 呼び出し内
シナリオ
-- パッケージ A が B を呼ぶ
CREATE PACKAGE pkg_a IS
PROCEDURE do_work;
END;
/
CREATE PACKAGE BODY pkg_a IS
PROCEDURE do_work IS
BEGIN
pkg_b.helper; -- B が変更されると ORA-04061
END;
END;
/
解決
両パッケージの依存関係管理、共通の再デプロイ。
診断ツール完全リファレンス
エラーコード確認
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -4061 THEN
DBMS_OUTPUT.PUT_LINE('State invalidated');
ELSIF SQLCODE = -4068 THEN
DBMS_OUTPUT.PUT_LINE('State discarded');
END IF;
END;
V$SESSION でセッション確認
SELECT sid, serial#, username, module, status, prev_sql_id
FROM v$session
WHERE username = 'APP_USER';
INVALID オブジェクト
SELECT owner, object_name, object_type, status
FROM all_objects
WHERE status = 'INVALID'
AND owner = 'APPS';
DBMS_SESSION 状態確認
-- 現セッションの状態リセット
BEGIN
DBMS_SESSION.RESET_PACKAGE;
END;
/
-- 全パッケージのグローバル状態クリア
Shared Pool フラッシュ(緊急対応)
ALTER SYSTEM FLUSH SHARED_POOL;
-- ⚠️ パフォーマンスに影響、慎重に
7つの解決策 完全リファレンス
解決策① 再実行(自動回復)
-- Oracle は次回呼び出しで状態を自動再初期化
BEGIN
my_pkg.proc_a; -- 初回: ORA-04061
END;
/
BEGIN
my_pkg.proc_a; -- 2 回目: 通常成功
END;
/
多くの場合これで解決。
解決策② グローバル状態除去
-- ❌ グローバル状態あり
CREATE PACKAGE bad_pkg AS
g_counter NUMBER := 0;
PROCEDURE increment;
END;
/
-- ✅ 状態を持たない設計
CREATE PACKAGE good_pkg AS
PROCEDURE increment(io_counter IN OUT NUMBER);
END;
/
CREATE PACKAGE BODY good_pkg AS
PROCEDURE increment(io_counter IN OUT NUMBER) IS
BEGIN
io_counter := io_counter + 1;
END;
END;
/
解決策③ PRAGMA SERIALLY_REUSABLE
CREATE PACKAGE reusable_pkg AS
PRAGMA SERIALLY_REUSABLE;
g_config VARCHAR2(100);
PROCEDURE proc_a;
END;
/
CREATE PACKAGE BODY reusable_pkg AS
PRAGMA SERIALLY_REUSABLE;
PROCEDURE proc_a IS
BEGIN
g_config := 'value'; -- 呼び出し毎にリセット
END;
END;
/
制約:
- SPEC と BODY 両方に必要
- サーバーサイドセッションでのみ効果
- 一部の PL/SQL 機能制限
解決策④ Functions 使用
-- Function は状態を持たない
CREATE FUNCTION get_config RETURN VARCHAR2 IS
BEGIN
RETURN 'value';
END;
/
-- パッケージから利用
CREATE PACKAGE BODY logic_pkg AS
PROCEDURE do_work IS
v_config VARCHAR2(100) := get_config;
BEGIN
...
END;
END;
/
解決策⑤ Edition-Based Redefinition (EBR)
Oracle 11g R2+ の高度な機能:
-- 新エディション作成
CREATE EDITION new_edition;
-- 新エディションでパッケージ変更
ALTER SESSION SET EDITION = new_edition;
CREATE OR REPLACE PACKAGE my_pkg AS ... END;
-- 既存セッションは旧エディションで動作継続
-- 新セッションのみ新エディション
-- → ORA-04061 回避
アップグレード後:
-- 全セッションで新エディション使用
ALTER DATABASE DEFAULT EDITION = new_edition;
解決策⑥ Rails 接続プールリセット
# デプロイ後
ActiveRecord::Base.connection_pool.disconnect!
# または個別接続
ActiveRecord::Base.connection.reconnect!
# マイグレーション内で
class ForceReconnect < ActiveRecord::Migration[8.0]
def up
# パッケージ変更
execute "ALTER PACKAGE my_pkg COMPILE BODY"
# 接続プール全リセット
ActiveRecord::Base.connection_pool.disconnect!
end
end
解決策⑦ SESSION_EXIT_ON_PACKAGE_STATE_ERROR (26ai)
Oracle 26ai 新機能:
-- セッションレベル
ALTER SESSION SET session_exit_on_package_state_error = TRUE;
-- システムレベル
ALTER SYSTEM SET session_exit_on_package_state_error = TRUE;
効果:
ORA-04061/04068 発生時
→ セッション自動切断
→ アプリの接続再取得ロジックで自動回復
→ silent data corruption 防止
推奨環境: 26ai 以降 + 接続プール使用アプリ。
Rails / Java / Python 対応
Rails ActiveRecord
自動リトライ + 接続リセット:
class PackageCaller
def self.call_with_retry(sql, max_retries: 3)
retries = 0
begin
ActiveRecord::Base.connection.execute(sql)
rescue ActiveRecord::StatementInvalid => e
if (e.message.include?("ORA-04061") || e.message.include?("ORA-04068")) \
&& retries < max_retries
retries += 1
Rails.logger.warn "Package state error, retry #{retries}"
ActiveRecord::Base.connection.reconnect!
retry
end
raise
end
end
end
# 使用
PackageCaller.call_with_retry("BEGIN my_pkg.proc_a; END;")
Rails 8 系の詳細は Rails 8 アップグレードガイドの記事も参照してください。
Java (JDBC)
public void callWithRetry(String sql, int maxRetries) throws SQLException {
int retries = 0;
while (true) {
try (Statement stmt = conn.createStatement()) {
stmt.execute(sql);
return;
} catch (SQLException e) {
if ((e.getErrorCode() == 4061 || e.getErrorCode() == 4068)
&& retries < maxRetries) {
retries++;
logger.warn("Package state error, retry " + retries);
conn.close();
conn = ds.getConnection();
} else {
throw e;
}
}
}
}
Python (oracledb)
import oracledb
def call_with_retry(dsn, user, pw, sql, max_retries=3):
for attempt in range(max_retries):
try:
with oracledb.connect(user=user, password=pw, dsn=dsn) as conn:
cursor = conn.cursor()
cursor.execute(sql)
return
except oracledb.DatabaseError as e:
error_obj, = e.args
if error_obj.code in (4061, 4068) and attempt < max_retries - 1:
print(f"Package state error, retry {attempt + 1}")
continue
raise
実践シナリオ
シナリオ1:Oracle EBS Workflow 障害対応
-- 1. INVALID オブジェクト確認
SELECT owner, object_name, object_type
FROM dba_objects
WHERE status = 'INVALID' AND owner = 'APPS';
-- 2. Notification Mailer 停止
-- (Concurrent Manager 経由)
-- 3. Shared Pool フラッシュ
SQL> CONN / AS SYSDBA
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
-- 4. APPS スキーマ再コンパイル
BEGIN
UTL_RECOMP.recomp_parallel(4, 'APPS');
END;
/
-- 5. Notification Mailer 再起動
-- 6. Workflow 再実行確認
シナリオ2:本番デプロイでの回避
# 1. アプリケーション一時停止
kamal app stop
# 2. パッケージ更新
sqlplus $DB_USER/$DB_PW <<EOF
@deploy_packages.sql
EOF
# 3. INVALID 確認
sqlplus / as sysdba <<EOF
SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';
EOF
# 4. アプリ再起動
kamal app start
Kamal 2 デプロイの詳細は Kamal 2 デプロイの記事を参照してください。
シナリオ3:Rails での耐障害設計
# config/initializers/oracle_retry.rb
module OracleRetry
def with_package_retry(max_retries: 3)
retries = 0
begin
yield
rescue ActiveRecord::StatementInvalid => e
if package_state_error?(e) && retries < max_retries
retries += 1
Rails.logger.warn "Package state error, retry #{retries}"
ActiveRecord::Base.connection.reconnect!
retry
end
raise
end
end
private
def package_state_error?(e)
e.message.include?("ORA-04061") || e.message.include?("ORA-04068")
end
end
# 使用
include OracleRetry
with_package_retry do
ActiveRecord::Base.connection.execute("BEGIN my_pkg.proc_a; END;")
end
シナリオ4:EBR による無停止デプロイ
-- 1. 新エディション作成
CREATE EDITION v2;
-- 2. 新エディションでパッケージ変更
ALTER SESSION SET EDITION = v2;
CREATE OR REPLACE PACKAGE my_pkg AS ... END;
-- 3. 既存セッションは v1 で動作継続
-- 新セッションのみ v2
-- 4. アプリ側で切り替え
ALTER SESSION SET EDITION = v2;
-- 5. 全セッション移行後
ALTER DATABASE DEFAULT EDITION = v2;
DROP EDITION v1 CASCADE;
シナリオ5:グローバル状態除去のリファクタリング
-- ❌ 変更前(グローバル状態あり)
CREATE PACKAGE order_pkg AS
g_current_order_id NUMBER;
PROCEDURE start_order(p_id NUMBER);
PROCEDURE add_item(p_item VARCHAR2);
END;
/
-- ✅ 変更後(状態レス)
CREATE PACKAGE order_pkg AS
PROCEDURE add_item(p_order_id NUMBER, p_item VARCHAR2);
END;
/
CREATE PACKAGE BODY order_pkg AS
PROCEDURE add_item(p_order_id NUMBER, p_item VARCHAR2) IS
BEGIN
INSERT INTO order_items(order_id, item)
VALUES (p_order_id, p_item);
END;
END;
/
シナリオ6:Docker Oracle でのテスト
docker exec -it oracle-xe sqlplus scott/tiger <<EOF
CREATE OR REPLACE PACKAGE test_pkg AS
g_counter NUMBER := 0;
PROCEDURE increment;
END;
/
CREATE OR REPLACE PACKAGE BODY test_pkg AS
PROCEDURE increment IS
BEGIN
g_counter := g_counter + 1;
DBMS_OUTPUT.PUT_LINE(g_counter);
END;
END;
/
BEGIN test_pkg.increment; END;
/
-- Output: 1
-- 別セッションで再コンパイル
-- ALTER PACKAGE test_pkg COMPILE BODY;
BEGIN test_pkg.increment; END;
/
-- ORA-04061 or ORA-04068
BEGIN test_pkg.increment; END;
/
-- 再実行で成功、Output: 1 (リセット済み)
EOF
Docker 関連は docker daemon 接続エラーの記事、Docker no space left on device の記事も参照してください。
シナリオ7:Oracle datapatch 対処
-- 19.10 パッチ適用前
SQL> CONN / AS SYSDBA
SQL> ALTER SYSTEM SET "_srvntfn_job_deq_timeout" = 0 SCOPE=SPFILE;
SQL> SHUTDOWN IMMEDIATE
SQL> STARTUP
-- datapatch 実行
$ORACLE_HOME/OPatch/datapatch -verbose
-- パッチ適用後
SQL> ALTER SYSTEM RESET "_srvntfn_job_deq_timeout" SCOPE=BOTH;
SQL> SHUTDOWN IMMEDIATE
SQL> STARTUP
シナリオ8:CI/CD パイプラインでの対応
- name: Deploy PL/SQL
run: |
# 1. アプリ停止
kubectl scale deployment app --replicas=0
# 2. パッケージ変更
sqlplus $DB_USER/$DB_PW <<EOF
@deploy_packages.sql
EOF
# 3. INVALID 確認
invalid=$(sqlplus -s / as sysdba <<EOF
SET HEADING OFF FEEDBACK OFF
SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';
EXIT;
EOF
)
if [ "$invalid" != "0" ]; then
echo "INVALID objects: $invalid"
exit 1
fi
# 4. アプリ再起動
kubectl scale deployment app --replicas=3
シナリオ9:Autonomous DB での対応
Autonomous DB では
- パッケージ管理は同様
- リトライロジック推奨
- 26ai なら SESSION_EXIT_ON_PACKAGE_STATE_ERROR 活用
シナリオ10:定期監視スクリプト
#!/bin/bash
# monitor_invalid.sh
invalid=$(sqlplus -s / as sysdba <<EOF
SET HEADING OFF FEEDBACK OFF
SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';
EXIT;
EOF
)
if [ "$invalid" -gt "0" ]; then
echo "INVALID objects detected: $invalid" | \
mail -s "Oracle INVALID Alert" ops@example.com
fi
crontab の詳細は crontab 使い方の記事も参照してください。
トラブルシューティング
再実行しても直らない
INVALID オブジェクトがあるか確認、再コンパイル:
ALTER PACKAGE my_pkg COMPILE BODY;
頻発する場合
根本原因はグローバル状態、リファクタリング検討。
DBMS_SESSION.RESET_PACKAGE の副作用
全パッケージ状態がリセット、業務中は慎重に。
Shared Pool フラッシュの影響
パフォーマンス低下(キャッシュクリア)、業務時間外推奨。
EBR の導入コスト
設計変更大、慎重に計画。
PostgreSQL からの移行
PG は関数ベース、パッケージ状態問題なし。移行時は状態管理見直し。
よくある質問(FAQ)
Q1. ORA-04061 と ORA-04068 の違い
- 04061: 状態が INVALIDATED(無効化)
- 04068: 状態が DISCARDED(破棄)
- 通常セットで発生
Q2. 併発エラー4種
ORA-04061, ORA-04065, ORA-06508, ORA-06512。
Q3. 再実行で解決するか
多くの場合 YES。Oracle が自動再初期化。
Q4. グローバル状態を避けるべき
推奨。パッケージ設計時に状態レス化。
Q5. PRAGMA SERIALLY_REUSABLE の使いどころ
頻繁に更新されるパッケージ、状態不要な場合。
Q6. EBR の推奨環境
24時間運用、無停止デプロイ必須。
Q7. Rails での対応
リトライロジック + 接続プールリセット。
Q8. Java での対応
errorCode == 4061 or 4068 で判定 + 接続再取得。
Q9. Oracle EBS での対処
Notification Mailer 再起動 + Shared Pool フラッシュ。
Q10. Oracle 26ai の新機能
SESSION_EXIT_ON_PACKAGE_STATE_ERROR で自動切断。
Q11. パフォーマンスへの影響
再コンパイル時のみ、通常はなし。
Q12. 予防策
- グローバル状態最小化
- デプロイ順序管理
- リトライロジック実装
- EBR 検討
参考リンク
Oracle 公式
- Oracle Database Error Messages: ORA-04061
- Oracle PL/SQL Language Reference: PRAGMA SERIALLY_REUSABLE
- Oracle Database Development Guide: Edition-Based Redefinition
- SESSION_EXIT_ON_PACKAGE_STATE_ERROR (26ai)
まとめ
ORA-04061: existing state of ... has been invalidated の要点を再整理します。
エラーの本質
セッションが保持していたパッケージ状態と
現在のパッケージ定義が不整合
→ INVALIDATED(無効化)
→ 通常 ORA-04068 とセットで発生
ORA-04061 vs ORA-04068
ORA-04061: INVALIDATED(無効化)
- コンパイル時に検出
- 状態はまだあるが使えない
ORA-04068: DISCARDED(破棄)
- 実行時に発生
- 状態自体が消えた
エラーメッセージの読み方
ORA-04061: existing state of package body "SCHEMA.PACKAGE" has been invalidated
↑
無効化されたオブジェクト
併発エラー4種
| エラー | 意味 |
|---|---|
| ORA-04061 | 状態が INVALIDATED |
| ORA-04065 | パッケージが変更/削除 |
| ORA-06508 | プログラムユニット発見不可 |
| ORA-06512 | 発生位置 |
10大原因
| # | 原因 | 対処 |
|---|---|---|
| ① | パッケージ再コンパイル中 | 再実行 |
| ② | Oracle EBS Workflow | adadmin 再コンパイル |
| ③ | グローバル状態あり | 除去 |
| ④ | Rails マイグレーション | 接続プールリセット |
| ⑤ | CI/CD デプロイ | 一時停止 |
| ⑥ | Oracle datapatch | 隠しパラメータ |
| ⑦ | 定数変更 | RESET_PACKAGE |
| ⑧ | 型変更 | 再接続 |
| ⑨ | Java Callable | 接続再取得 |
| ⑩ | PL/SQL 依存 | 共通デプロイ |
7つの解決策
-- ① 再実行(Oracle 自動回復)
BEGIN my_pkg.proc_a; END;
-- ② グローバル状態除去
-- IN OUT パラメータで状態を渡す
-- ③ PRAGMA SERIALLY_REUSABLE
CREATE PACKAGE my_pkg AS
PRAGMA SERIALLY_REUSABLE;
...
END;
-- ④ Functions 使用
-- 状態を持たない Function
-- ⑤ Edition-Based Redefinition
CREATE EDITION new_edition;
ALTER SESSION SET EDITION = new_edition;
# ⑥ Rails 接続プールリセット
ActiveRecord::Base.connection_pool.disconnect!
-- ⑦ 26ai 新機能
ALTER SYSTEM SET session_exit_on_package_state_error = TRUE;
各言語での対応
Rails: リトライ + connection_pool.disconnect!
Java: errorCode == 4061/4068 + 接続再取得
Python: DatabaseError.code チェック
共通: 接続再取得ロジック実装
予防のポイント
1. グローバル状態を最小化
2. PRAGMA SERIALLY_REUSABLE 活用
3. Functions で状態レス化
4. リトライロジック実装
5. デプロイ順序管理(アプリ停止)
6. Rails 接続プールリセット
7. EBR 検討(24時間運用)
8. 26ai の新機能活用
9. 定期的な INVALID オブジェクト監視
10. Oracle EBS は Vendor 手順遵守
これらの知識は、Oracle での PL/SQL 開発・パッケージ設計・DBA 運用・Oracle EBS 管理・Rails / Java / Python アプリ運用・CI/CD パイプライン・24時間運用・データベースアップグレードなど、あらゆる場面で活用できます。本記事をブックマークしておけば、ORA-04061 に出会っても冷静に的確に対処できるようになります。
本記事は2026年6月時点の情報をもとに、Oracle Database 19c〜26ai での動作確認・公式ドキュメントに基づき作成しています。Oracle のバージョンにより挙動が異なる場合があるため、最新の情報は Oracle 公式ドキュメント(docs.oracle.com)もあわせてご確認ください。
-
前の記事
【完全ガイド】ORA-01950: no privileges on tablespace の原因と解決方法|QUOTA・DEFAULT TABLESPACE・RESOURCE ロール 徹底解説 2026.08.21
-
次の記事
【完全ガイド】ORA-04065: not executed, altered or dropped package の原因と解決方法|3兄弟完全比較・Shared Pool・EBR 徹底解説 2026.08.25
コメントを書く