首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle 經典 10 問 (三):MEMO 空值、跨表更新、P4 安裝、OPS 判斷、用戶權限、移動表/索引、DBA Studio、鎖查詢、解鎖

     編輯:Oracle 資料庫相關知識

前言:第 3 期 10 題——資料操作、架構識別、權限、空間管理、鎖診斷

涵蓋 LOB 空值判斷、跨表更新語法、硬體相容性、RAC/OPS 判斷、權限審計、表索引跨表空間移動、OEM 啟動、鎖全景查詢、Session 殺除——核心 DBA 技能組合包。

Q21: 如何查詢 MEMO (CLOB/長文本) 欄位為空的記錄?

-- CLOB/NCLOB/BLOB 判斷空值 (含空字串)
SELECT * FROM oms_flowrec
WHERE remark IS NULL
   OR TRIM(remark) IS NULL
   OR LENGTH(remark) = 0
   OR DBMS_LOB.GETLENGTH(remark) = 0;  -- 針對 LOB 型別最準確

-- 反向: 非空記錄
SELECT remark FROM oms_flowrec
WHERE remark IS NOT NULL
  AND TRIM(remark) IS NOT NULL
  AND DBMS_LOB.GETLENGTH(remark) > 0;

關鍵:TRIM(' ' FROM remark) 語法為 ANSI 標準,Oracle 支援。LOB 欄位 LENGTH() 隱性轉換可能慢,優先 DBMS_LOB.GETLENGTH。

Q22: 如何用 BBB 表資料更新 AAA 表 (關聯欄位)?

-- 相關子查詢 (單欄更新)
UPDATE aaa
SET bns_snm = (SELECT bns_snm FROM bbb WHERE aaa.dpt_no = bbb.dpt_no)
WHERE EXISTS (SELECT 1 FROM bbb WHERE aaa.dpt_no = bbb.dpt_no);

-- 多欄更新 (Oracle 10g+ 支援)
UPDATE aaa
SET (col1, col2, col3) = (
    SELECT b.col1, b.col2, b.col3
    FROM bbb b
    WHERE aaa.dpt_no = b.dpt_no
)
WHERE EXISTS (SELECT 1 FROM bbb WHERE aaa.dpt_no = bbb.dpt_no);

-- MERGE 語句 (10g+ 標準寫法, 效能最佳、語義清晰)
MERGE INTO aaa a
USING bbb b
ON (a.dpt_no = b.dpt_no)
WHEN MATCHED THEN UPDATE SET a.bns_snm = b.bns_snm;

原則:優先 MERGE (單掃描、可並行、可錯誤記錄 LOG ERRORS);子查詢確保 WHERE EXISTS 避免更新無匹配行置 NULL。

Q23: P4 (奔騰 4) 電腦安裝 Oracle 相容性處理?

歷史背景:早期 Oracle 8i/9i 安裝程式 (JRE 1.1/1.2) 在 P4 的 SSE2 指令集下會崩潰,症狀為安裝精靈閃退或 SYMCJIT.DLL (Symantec JIT 編譯器) 故障。

-- 臨時修補 (安裝前)
RENAME SYMCJIT.DLL TO SYMCJIT.OLD
-- 位置: $ORACLE_HOME/JRE/1.1.8/bin/ 或 Windows System32

現代環境:Oracle 10g+ 內建 JRE 1.4+ 完美支援 SSE2/SSE3/AVX,無此問題。純歷史參考。

Q24: 如何判斷資料庫是否為 OPS/RAC (Parallel Server)?

-- 查詢選項視圖
SELECT parameter, value FROM v$option WHERE parameter = 'Parallel Server';
-- VALUE = 'TRUE' 表示啟用 OPS/RAC (安裝了 Clusterware、配置了共享存儲)
-- 9i 稱為 OPS (Oracle Parallel Server), 10g+ 稱為 RAC (Real Application Clusters)

-- 進一步確認實例數
SELECT instance_number, instance_name, host_name, status, parallel
FROM gv$instance;
-- 多行且 parallel='YES' 確為 RAC

Q25: 如何查詢每個用戶的系統權限?

-- 直接授予的系統權限
SELECT grantee, privilege, admin_option
FROM dba_sys_privs
ORDER BY grantee, privilege;

-- 角色授予 (間接權限)
SELECT grantee, granted_role, admin_option, default_role
FROM dba_role_privs
ORDER BY grantee, granted_role;

-- 完整權限報表 (系統+角色+物件)
-- 參考 Oracle 權限審計腳本 (如 PET, DBMS_METADATA)

Q26: 如何將表移動到另一個表空間?

-- 9i+ 線上移動 (需 Enterprise Edition)
ALTER TABLE table_name MOVE TABLESPACE new_tablespace;

-- 伴隨操作: 索引必須重建 (MOVE 後索引狀態 UNUSABLE)
-- 方法 1: 移動表時同時重建索引 (12.2+)
ALTER TABLE table_name MOVE TABLESPACE new_tablespace
  UPDATE INDEXES;  -- 自動重建所有索引至同表空間

-- 方法 2: 手動重建索引 (指定表空間)
ALTER INDEX idx_name REBUILD TABLESPACE new_index_tablespace;

-- 方法 3: DBMS_REDEFINITION 線上重定義 (零停機, EE)
-- 適用大表、需保持 DML 可用

注意:MOVE 鎖表 (排他鎖),大表建議維護窗口或用 DBMS_REDEFINITION。

Q27: 如何將索引移動到另一個表空間?

-- 標準重建 (鎖表)
ALTER INDEX index_name REBUILD TABLESPACE new_tablespace;

-- 線上重建 (EE, 僅短暫鎖)
ALTER INDEX index_name REBUILD ONLINE TABLESPACE new_tablespace;

-- 並行重建 (大索引加速)
ALTER INDEX index_name REBUILD TABLESPACE new_tablespace PARALLEL 8;

-- 移動後統計資訊失效,需重新收集
EXEC DBMS_STATS.GATHER_INDEX_STATS('SCHEMA', 'INDEX_NAME');

Q28: Linux/Unix 下如何啟動 DBA Studio (OEM 獨立控制台)?

# 環境變數已載入 (ORACLE_HOME, PATH)
oemapp dbastudio
# 或
$ORACLE_HOME/bin/oemapp dbastudio

背景:DBA Studio 為 9i/10g 客戶端圖形化管理工具 (Java Swing),11g+ 被 Web 版 Enterprise Manager (Cloud Control) 取代。現代環境請使用 EMCTL 管理 Cloud Control。

Q29: 查詢鎖狀況涉及哪些視圖?標準鎖查詢 SQL?

核心視圖:V$LOCK, V$LOCKED_OBJECT, V$SESSION, V$SQLAREA, V$PROCESS。

-- 標準鎖全景查詢 (識別阻塞鏈、SQL、OS 進程)
SELECT
    s.sid,
    s.serial#,
    s.username,
    s.machine,
    s.osuser,
    s.program,
    s.sql_id,
    l.type,
    DECODE(l.lmode, 0,'None',1,'Null',2,'Row-S (SS)',3,'Row-X (SX)',4,'Share',5,'S/Row-X (SSX)',6,'Exclusive',TO_CHAR(l.lmode)) AS mode_held,
    DECODE(l.request, 0,'None',1,'Null',2,'Row-S (SS)',3,'Row-X (SX)',4,'Share',5,'S/Row-X (SSX)',6,'Exclusive',TO_CHAR(l.request)) AS mode_requested,
    o.owner || '.' || o.object_name || ' (' || o.object_type || ')' AS locked_object,
    p.spid AS os_pid,
    sq.sql_text
FROM v$lock l
JOIN v$session s ON s.sid = l.sid
JOIN v$process p ON p.addr = s.paddr
LEFT JOIN dba_objects o ON o.object_id = l.id1
LEFT JOIN v$sqlarea sq ON sq.sql_id = s.sql_id
WHERE l.type IN ('TX','TM','UL')  -- 交易鎖、DML鎖、用戶鎖
  AND (l.lmode > 0 OR l.request > 0)
ORDER BY l.ctime DESC;  -- 持鎖時間最長在前

關鍵欄位:LMODE (持有模式), REQUEST (請求模式), ID1/ID2 (鎖標識),TX 行鎖, TM 表鎖, UL 用戶定義鎖 (DBMS_LOCK)。

Q30: 如何解鎖 (殺掉阻塞 Session)?

-- 1. 優雅終止 (讓事務回滾釋放鎖)
ALTER SYSTEM KILL SESSION 'SID,SERIAL#' IMMEDIATE;
-- IMMEDIATE: 立即斷開連接、回滾事務、釋放鎖、標記 KILLED,不等待當前調用返回

-- 2. 強制終止 (OS 層面, 當 IMMEDIATE 無效或進程卡死)
-- 先查 OS PID
SELECT spid FROM v$process WHERE addr = (SELECT paddr FROM v$session WHERE sid = &SID);
-- OS 執行 (需 root/oracle 權限)
kill -9 SPID

-- 3. RAC 環境: 指定實例
ALTER SYSTEM KILL SESSION 'SID,SERIAL#,@INST_ID' IMMEDIATE;

原則:優先 IMMEDIATE (讓 PMON 清理);僅在資源耗盡、PMON 無響應時用 kill -9 (風險:共享記憶體殘留、Data Guard 傳輸中斷)。

總結

第 3 期 10 題構成「資料操作 (LOB/更新)、架構識別 (OPS/RAC)、權限審計、空間重組 (MOVE/REBUILD)、鎖診斷與處置」完整技能鏈。建議製成「鎖排查單頁流程圖」:鎖等待告警 → 跑 Q29 SQL → 定阻塞 SID/SQL/OS PID → 業務確認 → KILL IMMEDIATE → 驗證釋放 → 記錄歸檔,新人依圖索驥,資深優化預防。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved