Oracle 資料庫運行久了,總會遇到各種詭異問題:壞塊、FORM/REPORT 異常、動態查詢、約束管理、歸檔模式切換、表空間擴容、動態顯示域... 本文精選 10 個高頻實戰場景,提供標準化解決腳本與最佳實務,助你從「被動救火」轉向「主動防火」。
DBVERIFY 掃描資料檔,獲取壞塊 ID(假設 1234)。SELECT segment_name, segment_type, block_id, blocks
FROM dba_extents
WHERE 1234 BETWEEN block_id AND (block_id + blocks - 1);
DROP INDEX ...; CREATE INDEX ...; 重建,無需搶救資料。CREATE TABLE good_table AS
SELECT * FROM bad_table
WHERE rowid NOT IN (
SELECT /*+ INDEX(bad_table, any_index) */ rowid
FROM bad_table
WHERE substr(rowid, 1, 8) = '000004D2' -- 壞塊相對檔案號+塊號轉十六進位
);
DB_BLOCK_CHECKSUM=FULL、DB_LOST_WRITE_PROTECT=TYPICAL 早期發現壞塊。BLOCKRECOVER 單塊恢復,若有完整備份與歸檔。Forms/Reports 架構中,REPORT BACKGROUND ENGINE 為共享後台服務,Forms 退出後該視窗殘留。解法:在 RUN_REPORT_OBJECT 參數列表第一個參數加入:
Add_Parameter(pl_id, 'ORACLE_SHUTDOWN', TEXT_PARAMETER, 'Yes');
關鍵:必須為第一個參數,否則無效。此參數指示 Reports Server 作業完成後自動關閉引擎視窗。
W_CLAUSE (CHAR, 初始值 NULL)。Q_1:SELECT * FROM dept &&W_CLAUSE。SET_REPORT_OBJECT_PROPERTY(rep_id, REPORT_OTHER, 'PARAMFORM=NO W_CLAUSE="WHERE dept=1"')。原理:&&W_CLAUSE 為詞法參數,運行時直接替換 SQL 片段,支援任意複雜 WHERE 子句(含子查詢、函數)。
-- 核心約束資訊
SELECT constraint_name, table_name, constraint_type, status, r_owner, r_constraint_name
FROM all_constraints
WHERE table_name = UPPER('YOUR_TABLE') AND owner = UPPER('SCHEMA');
-- 約束包含欄位明細
SELECT ac.constraint_name, acc.column_name, acc.position
FROM all_cons_columns acc
JOIN all_constraints ac ON ac.constraint_name = acc.constraint_name AND ac.owner = acc.owner
WHERE acc.table_name = UPPER('YOUR_TABLE') AND acc.owner = UPPER('SCHEMA')
ORDER BY ac.constraint_name, acc.position;
ALL_CONS_COLUMNS 視圖提供欄位級明細,包含複合索引欄位順序。
-- 1. 確認 init.ora / spfile 歸檔目標目錄有效
LOG_ARCHIVE_DEST_1 = 'LOCATION=/u01/app/oracle/arch VALID_FOR=(ALL_LOGFILES,ALL_ROLES)'
-- 2. 關閉資料庫 -> 掛載 -> 開啟歸檔 -> 開啟資料庫
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
-- 3. 驗證
ARCHIVE LOG LIST;
-- 輸出應顯示:Database log mode: Archive Mode, Automatic archival: Enabled
-- 4. 11g+ 多歸檔目的地
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='LOCATION=/u02/app/oracle/arch2' SCOPE=BOTH;
注意:切換前必須完成一次完整冷備份,切換後立即執行熱備份建立基線。
| 方式 | 語法 | 適用場景 | 優/缺點 |
|---|---|---|---|
| 新增資料檔 | ALTER TABLESPACE users ADD DATAFILE '/u01/oradata/orcl/users02.dbf' SIZE 25M AUTOEXTEND ON NEXT 10M MAXSIZE 1G; | 檔案系統剩餘空間充足、需分散 I/O | ✅ 可跨磁碟分散 I/O;❌ 管理檔案數增加 |
| 擴充現有檔案 | ALTER DATABASE DATAFILE '/u01/oradata/orcl/users01.dbf' RESIZE 50M; | 單一大檔案管理、ASM 環境 | ✅ 管理簡單;❌ 受限於檔案系統/ASM 磁碟組剩餘空間 |
最佳實務:啟用 AUTOEXTEND ON MAXSIZE UNLIMITED,配合監控告警(使用率 > 85% 觸發擴容工單),實現零人工干預擴容。
RQ (CHAR)。F_1 → 來源指向 RQ → 設為「不可見」。D_1 → 內容輸入 &&F_1 → 調整位置寬度。運行時,D_1 即顯示 Form 傳入的 RQ 值(如日期、報表標題)。
SELECT s.sid, s.serial#, s.username, s.machine, s.sql_id, t.sql_text
FROM v$session s
JOIN v$sqltext t ON t.address = s.sql_address AND t.hash_value = s.sql_hash_value
WHERE s.status = 'ACTIVE' AND s.type = 'USER'
ORDER BY s.sid, t.piece;
搭配 DBMS_MONITOR.SESSION_TRACE_ENABLE 可生成 10046 Trace 深度分析。
-- 1. 找阻塞鏈
SELECT blocking_session, sid, serial#, seconds_in_wait, event, sql_id
FROM v$session
WHERE blocking_session IS NOT NULL;
-- 2. 獲取完整 SQL
SELECT sql_text FROM v$sql WHERE sql_id = '&SQL_ID';
-- 3. 優雅終止 (先嘗試)
ALTER SYSTEM KILL SESSION 'SID,SERIAL#' IMMEDIATE;
-- 4. 強制終止 (OS 層面)
-- 查詢 SPID
SELECT spid FROM v$process WHERE addr = (SELECT paddr FROM v$session WHERE sid = &SID);
-- OS 執行: kill -9 SPID
原則:優先 IMMEDIATE 讓事務回滾釋放鎖;僅在資源耗盡時用 OS kill。
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'GATHER_STATS_DAILY',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN DBMS_STATS.GATHER_DATABASE_STATS_OPTIONS( options => ''GATHER AUTO'' ); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0; BYSECOND=0',
enabled => TRUE,
comments => 'Daily auto stats gather for CBO'
);
END;
/
利用 GATHER AUTO 讓 Oracle 自動判斷哪些物件統計過期,避免全庫掃描浪費資源。
這 10 個場景覆蓋了儲存、備份、應用整合、效能、維護等核心領域。建議將每個解決方案封裝為標準化 Runbook(含腳本、驗證步驟、回滾方案),納入團隊知識庫,新人入職即可上手,資深 DBA 專注架構優化而非重複造輪子。