DUAL 是 Oracle 內建單列單行虛擬表,無數 SQL 依賴它 (如 SELECT SYSDATE FROM DUAL)。誤執行 DROP TABLE dual 會導致資料庫無法啟動 (ORA-1092)。本文提供經實測驗證的最小停機恢復流程。
DROP TABLE sys.dual 後,資料庫仍可運作 (字典快取殘留)。ORA-01092: ORACLE instance terminated. Disconnection forced、ORA-00600: internal error code, arguments: [qcsfndps], [dual]。SMON: enabling tx recovery 後終止。SQL> CREATE PFILE='/tmp/pfile_backup.ora' FROM SPFILE;
SQL> SHUTDOWN IMMEDIATE;
編輯 /tmp/pfile_backup.ora,於末尾新增:
replication_dependency_tracking = FALSE
原理:此隱藏參數關閉複製環境的相依性追蹤,避免啟動階段查詢 DUAL 觸發遞迴錯誤。
SQL> STARTUP PFILE='/tmp/pfile_backup.ora' MOUNT;
若報錯嘗試 STARTUP RESTRICT PFILE=... 限制非 DBA 連線。
SQL> ALTER DATABASE OPEN; -- 若 MOUNT 成功可直接 OPEN
-- 或若 OPEN 失敗,在 MOUNT 狀態下:
SQL> CREATE TABLE "SYS"."DUAL" (DUMMY VARCHAR2(1));
SQL> INSERT INTO "SYS"."DUAL" VALUES ('X');
SQL> COMMIT;
SQL> SELECT * FROM dual; -- 應回傳 'X'
SQL> SHUTDOWN IMMEDIATE;
-- 移除 replication_dependency_tracking=FALSE
SQL> STARTUP; -- 使用原 SPFILE 正常啟動
SQL> SELECT * FROM dual;
-- 現代版本 DUAL 為公用同義詞指向 SYS.DUAL$
-- 若上述簡易建表失效,嘗試標準定義:
CREATE TABLE sys.dual (dummy VARCHAR2(1));
INSERT INTO sys.dual VALUES ('X');
COMMIT;
CREATE PUBLIC SYNONYM dual FOR sys.dual;
GRANT SELECT ON sys.dual TO PUBLIC;
CREATE OR REPLACE TRIGGER prevent_drop_dual
BEFORE DROP ON DATABASE
WHEN (ORA_DICT_OBJ_OWNER = 'SYS' AND ORA_DICT_OBJ_NAME = 'DUAL')
BEGIN
RAISE_APPLICATION_ERROR(-20001, 'PROHIBITED: DUAL table cannot be dropped');
END;
/
AUDIT DROP TABLE BY ACCESS WHENEVER SUCCESSFUL;。同樣導致啟動失敗。恢復原則相同:replication_dependency_tracking=FALSE + PFILE 啟動 + 從備份/同版本資料庫匯出建立腳本重建。建議維護 **核心字典表建立腳本庫** 以備不時之需。