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

Oracle VPD 虛擬私有數據庫實戰:五種策略類型性能演進與上下文敏感最佳實踐

     編輯:Oracle 資料庫基礎

核心概念

VPD (Virtual Private Database) = 細粒度訪問控制 (FGAC) = 行級安全 (RLS)。通過策略函數動態在查詢上附加 WHERE 謂詞,實現「同表不同視圖」。

五種策略類型 (10g+)

類型常量重新求值觸發條件典型場景性能
DBMS_RLS.DYNAMIC每行、每次查詢謂詞極度動態 (如基於行屬性計算)★
DBMS_RLS.CONTEXT_SENSITIVE會話上下文屬性變化謂詞依賴 SYS_CONTEXT,會話內穩定★★★★
DBMS_RLS.SHARED_CONTEXT_SENSITIVE跨會話共享上下文變化多租戶 SaaS,租戶上下文共享★★★★★
DBMS_RLS.STATIC僅首次 (SGA 緩存謂詞)謂詞由登錄用戶完全決定,會話不變★★★★★★
DBMS_RLS.SHARED_STATIC跨會話共享 SGA 緩存報表固定過濾、多用戶同謂詞★★★★★★★

實戰代碼:從動態到上下文敏感

1. 基礎動態策略 (兼容 9i)

CREATE OR REPLACE FUNCTION vpd_dyn (p_schema VARCHAR2, p_obj VARCHAR2)
RETURN VARCHAR2 IS
BEGIN
  RETURN 'am_name = ''' || SYS_CONTEXT('USERENV','SESSION_USER') || '''';
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    object_schema => 'SCOTT', object_name => 'ACCOUNTS',
    policy_name   => 'DYN_ACCT', function_schema => 'SEC_ADMIN',
    policy_function => 'VPD_DYN', policy_type => DBMS_RLS.DYNAMIC
  );
END;
/

2. 上下文敏感策略 (推薦 90% 業務)

-- 應用上下文
CREATE OR REPLACE CONTEXT vpd_ctx USING pkg_vpd_ctx;

-- 策略函數:謂詞前綴固定,數值取自上下文
CREATE OR REPLACE FUNCTION vpd_ctx_sens (p_schema VARCHAR2, p_obj VARCHAR2)
RETURN VARCHAR2 IS
BEGIN
  RETURN 'balance < ' || SYS_CONTEXT('VPD_CTX','MAX_BAL');
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    policy_name => 'CTX_BAL',
    policy_type => DBMS_RLS.CONTEXT_SENSITIVE,  -- 關鍵
    ...
  );
END;
/

登錄後設置:DBMS_SESSION.SET_CONTEXT('VPD_CTX','MAX_BAL', 100000);
會話期間 MAX_BAL 不變 → 函數不再執行 → 極高性能。

3. 靜態策略 (極致性能,謹慎用)

CREATE OR REPLACE FUNCTION vpd_stat (p_schema VARCHAR2, p_obj VARCHAR2)
RETURN VARCHAR2 IS
BEGIN
  RETURN 'cust_name = ' || SYS_CONTEXT('VPD_CTX','CUST_NAME');
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    policy_type => DBMS_RLS.STATIC,  -- 僅求值一次
    ...
  );
END;
/

⚠️ 風險:若會話中 CUST_NAME 變更,謂詞不刷新 → 數據錯誤!
僅用於「用戶登錄後謂詞終身不變」場景 (如固定租戶 ID)。

性能優化檢查清單

  1. 謂詞列 (如 balance) 必須有索引。
  2. 策略函數禁止查表,所有動態值走 SYS_CONTEXT。
  3. 盡量用 CONTEXT_SENSITIVE 替代 DYNAMIC。
  4. 多會話共享相同上下文屬性 → SHARED_CONTEXT_SENSITIVE。
  5. 12c+ 可結合 DBMS_REDACT 實現列級掩碼 (VPD 行級 + Redact 列級)。

常見錯誤與排查

  • ORA-28113: policy predicate has error → 函數返回非法 SQL 片段 (如缺少引號)。
  • 謂詞不生效 → 檢查 DBMS_RLS.ADD_POLICY 的 sec_relevant_cols / sec_relevant_cols_opt 參數。
  • 性能未提升 → 確認是否真正用上 CONTEXT_SENSITIVE,且上下文屬性會話內未變。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved