首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 細粒度存取控制 (FGAC/VPD) 完整架構與五大策略類型效能優化指南

     編輯:Oracle 資料庫基礎

Virtual Private Database (VPD),即細粒度存取控制 (Fine-Grained Access Control, FGAC),是 Oracle 企業級安全的核心:以行級安全策略,在查詢重寫階段透明附加謂詞,實現「同一張表、不同使用者看到不同資料」,零應用程式修改。10g 引入四種新策略類型,配合應用程式上下文,提供從「每行每次重算」到「SGA 快取重用」的效能光譜。本文系統解析 VPD 架構、五大策略類型、適用場景與陷阱避坑。

VPD 核心運作機制

  1. 策略函數:PL/SQL 函數,輸入 schema, table,回傳 VARCHAR2 謂詞片段 (如 dept_id = SYS_CONTEXT('ctx', 'dept'))。
  2. 註冊策略:DBMS_RLS.ADD_POLICY 綁定函數至物件,指定 POLICY_TYPE。
  3. 查詢重寫:使用者執行 SELECT * FROM accounts → Oracle 內部重寫為 SELECT * FROM accounts WHERE <謂詞>。
  4. 透明性:應用程式、報表工具、甚至 DBA (若未免除) 均受策略約束。

五大策略類型:從動態到靜態的效能光譜

策略類型參數值重新評估頻率謂詞特徵適用場景效能
Dynamic (預設、9i 相容) DBMS_RLS.DYNAMIC 每次存取、每行、每使用者 高度動態,依賴 Session/User/系統狀態 複雜權限邏輯、即時變動需求 最低 (CPU 高)
Context Sensitive DBMS_RLS.CONTEXT_SENSITIVE 應用程式上下文變更時 謂詞結構固定,僅參數值動態 (如 balance < SYS_CONTEXT('ctx','max')) Web 應用共用 DB User、上下文驅動權限 中 (避免重複評估)
Shared Context Sensitive DBMS_RLS.SHARED_CONTEXT_SENSITIVE 跨會話共享上下文變更時 同上,但謂詞在 SGA 共享池快取,多會話重用 大量併發會話、相同上下文值 中高
Static DBMS_RLS.STATIC 僅第一次載入 (SGA 快取永久) 完全靜態,謂詞不含 Session 變數 (如 cust_name = 'ACME') 托管環境、固定租戶隔離、登入觸發器設定上下文 最高 (近零開銷)
Shared Static DBMS_RLS.SHARED_STATIC 跨會話共享,永久快取 同上,多會話共享同一謂詞快取 大規模 SaaS、固定分區策略 最高

關鍵範例:從 Dynamic 到 Static 的演進

1. Dynamic (預設行為)

CREATE OR REPLACE FUNCTION vpd_dynamic_f (p_schema VARCHAR2, p_table VARCHAR2)
RETURN VARCHAR2 AS
BEGIN
  RETURN 'dept_id = ' || SYS_CONTEXT('USERENV', 'SESSION_USER'); -- 每次皆算
END;
/
BEGIN
  DBMS_RLS.ADD_POLICY(
    object_schema   => 'SCOTT',
    object_name     => 'EMP',
    policy_name     => 'EMP_DYNAMIC',
    function_schema => 'SEC_ADMIN',
    policy_function => 'VPD_DYNAMIC_F',
    policy_type     => DBMS_RLS.DYNAMIC  -- 可省略,預設即此
  );
END;
/

2. Context Sensitive (上下文驅動,避免重複計算)

-- 應用上下文:由中介層登入後 SET CONTEXT
CREATE OR REPLACE CONTEXT vpd_ctx USING vpd_pkg;

CREATE OR REPLACE FUNCTION vpd_cs_f (p_schema VARCHAR2, p_table VARCHAR2)
RETURN VARCHAR2 AS
BEGIN
  RETURN 'balance < SYS_CONTEXT(''VPD_CTX'', ''MAX_BAL'')'; -- 結構固定,參數來自上下文
END;
/
BEGIN
  DBMS_RLS.ADD_POLICY(
    policy_type => DBMS_RLS.CONTEXT_SENSITIVE,  -- 關鍵差異
    ...);
END;
/
-- 效能機制:若會話期間 VPD_CTX.MAX_BAL 未變,Oracle 跳過函數執行,直接重用謂詞

3. Static (托管/多租戶極致效能)

CREATE OR REPLACE FUNCTION vpd_static_f (p_schema VARCHAR2, p_table VARCHAR2)
RETURN VARCHAR2 AS
BEGIN
  RETURN 'cust_id = SYS_CONTEXT(''VPD_CTX'', ''CUST_ID'')'; -- 謂詞結構+值皆固定
END;
/
BEGIN
  DBMS_RLS.ADD_POLICY(
    policy_type => DBMS_RLS.STATIC,  -- 只執行一次,結果快取於 SGA
    ...);
END;
/
-- ⚠️ 風險:若會話中 CUST_ID 變更,謂詞不會更新 → 資料洩露/錯誤隔離
-- 必須保證:登入後上下文不可變,或登出重登

進階主題

共享策略類型

SHARED_* 類型將謂詞快取於共享池 (Shared Pool),而非私有 PGA。適合大量會話共用相同上下文值 (如多租戶 SaaS),減少記憶體佔用與 CPU。需設定 SHARED_CONTEXT_SENSITIVE 時指定 NAMESPACE 參數。

策略組

DBMS_RLS.CREATE_POLICY_GROUP 將多個策略分組,應用程式透過 DBMS_RLS.ADD_GROUPED_POLICY 動態啟用/停用群組,實現多層級安全 (如:基礎隔離組 + 業務規則組 + 合規審計組)。

免除策略

DBMS_RLS.ADD_POLICY(..., SEC_RELEVANT_COLS => 'SALARY', SEC_RELEVANT_COLS_OPT => DBMS_RLS.ALL_ROWS):僅當查詢涉及敏感欄位 (如薪資) 時套用謂詞,其他查詢不受限。EXEMPT ACCESS POLICY 系統權限可讓特定使用者 (如 DBA、批次帳號) 繞過所有 VPD。

效能調優清單

  1. 優先評估 Static/Shared Static:若業務允許「登入後權限固定」,效能提升數量級。
  2. 次選 Context Sensitive:Web 應用共用 DB User 時的標準選擇,配合中介層 DBMS_SESSION.SET_CONTEXT。
  3. 避免 Dynamic:除非謂詞邏輯極度複雜且必須即時計算,否則為效能殺手。
  4. 謂詞簡潔化:回傳簡單等值/範圍條件,避免子查詢、函數呼叫、複雜 OR 邏輯。
  5. 索引支撐:確保謂詞欄位有合適索引,否則全表掃描放大 VPD 開銷。
  6. 監控視圖:V$VPD_POLICY、V$RLS_POLICY 觀察策略命中與評估次數。

總結

VPD 以「查詢重寫」實現零侵入行級安全。策略類型選擇即效能架構決策:Static > Shared Static > Shared Context Sensitive > Context Sensitive > Dynamic。準確識別業務的「權限變動頻率與範圍」,選對類型、設計好上下文、配合索引,即可在安全合規與高併發效能間取得最佳平衡。

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