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

Oracle VPD 細粒度訪問控制:從動態策略到靜態緩存的演進與實戰

     編輯:Oracle 資料庫基礎

什麼是 VPD (Virtual Private Database)?

VPD = 細粒度訪問控制 (FGAC) = 行級安全 (RLS)。通過在查詢重寫階段透明附加謂詞,實現「同一張表,不同用戶見不同行」,無需修改應用 SQL。

核心組件

  • 策略函數:返回謂詞字符串(如 'dept_id = 10')。
  • 策略定義:DBMS_RLS.ADD_POLICY 綁定表、函數、策略類型。
  • 應用上下文:SYS_CONTEXT('namespace','attr') 實現動態變量注入。

五種策略類型性能演進 (10g+)

類型重新求值頻率適用場景性能
DYNAMIC (默認)每行、每次查詢謂詞高度動態(如基於行級業務規則)最低
CONTEXT_SENSITIVE會話上下文變化時謂詞依賴 SYS_CONTEXT,會話內相對穩定高
SHARED_CONTEXT_SENSITIVE跨會話共享上下文變化時多會話共享同一上下文屬性(如多租戶 SaaS)更高
STATIC僅首次載入 (SGA 緩存)謂詞完全由登錄用戶決定,會話內永不變最高
SHARED_STATIC跨會話共享 SGA 緩存多用戶共享相同謂詞(如報表固定過濾)極高

實戰代碼範例

1. 動態策略 (9i 風格,兼容性最好)

CREATE OR REPLACE FUNCTION vpd_dynamic (
  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_DYNAMIC',
    policy_type => DBMS_RLS.DYNAMIC
  );
END;
/

2. 上下文敏感策略 (推薦大多數業務)

CREATE OR REPLACE FUNCTION vpd_ctx_sens (
  p_schema VARCHAR2, p_obj VARCHAR2
) RETURN VARCHAR2 IS
BEGIN
  RETURN 'balance < ' || SYS_CONTEXT('VPDCTX','MAXBAL');
END;
/

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

應用登錄後設置上下文:

CREATE OR REPLACE CONTEXT VPDCTX USING pkg_vpd_ctx;
-- 登錄觸發器中
DBMS_SESSION.SET_CONTEXT('VPDCTX','MAXBAL', 100000);

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

CREATE OR REPLACE FUNCTION vpd_static (...) RETURN VARCHAR2 IS
BEGIN
  RETURN 'cust_name = ' || SYS_CONTEXT('VPDCTX','CUST_NAME');
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    policy_type => DBMS_RLS.STATIC,  -- 只求值一次,SGA緩存
    ...
  );
END;
/

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

性能優化檢查清單

  1. 謂詞前綴(列名、操作符)固定 → 用 CONTEXT_SENSITIVE。
  2. 謂詞完全固定 → 用 STATIC。
  3. 多會話共享相同上下文 → 用 SHARED_* 類型。
  4. 為策略函數引用的上下文屬性創建索引(如 balance 列)。
  5. 避免在策略函數中執行複雜 SQL 查詢,改用上下文預載值。

12c+ 新特性:默認全遮罩 (DEFAULT_FULL_REDACTION)

配合 DBMS_REDACT 可在 VPD 之上再做列級掩碼(如信用卡號只顯示後四位),實現「行級過濾 + 列級掩碼」雙層防護。

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