Virtual Private Database(VPD,虛擬私有資料庫)是 Oracle 8i 引入的行級安全功能。它透過動態修改用戶查詢、在 WHERE 子句自動附加謂詞,實現「同一張表、不同用戶看到不同資料」的效果,且對應用程式完全透明。
SELECT * FROM accounts)。am_name = 'SCOTT')。SELECT * FROM accounts WHERE am_name = 'SCOTT' 並執行。謂詞通常包含 靜態部分(欄位名、運算子)與 動態部分(用戶身分、權限、應用上下文變數)。在 Oracle 9i 及之前,預設為 Dynamic Policy:每次查詢、每行資料都重新執行策略函數,對高併發系統造成巨大 CPU 開銷。
針對謂詞「靜態程度」不同,提供效能優化選項:
適用場景:謂詞結構固定,僅應用上下文變數(如 SYS_CONTEXT('vpdctx', 'maxbal'))隨會話改變。
機制:若會話期間上下文屬性未變,Oracle **跳過策略函數重新執行**,直接復用上次謂詞。
DBMS_RLS.ADD_POLICY(..., policy_type => DBMS_RLS.CONTEXT_SENSITIVE);
適用場景:謂詞完全由資料庫用戶決定,會話間不變(如多租戶共用 APPUSER,登入觸發器設定 CUST_NAME)。
機制:謂詞在 SGA 快取,**策略函數僅執行一次**(首次解析時),後續查詢直接復用,速度最快。
DBMS_RLS.ADD_POLICY(..., policy_type => DBMS_RLS.STATIC);
⚠️ 風險:若會話中上下文實際被修改,靜態策略**不會重新評估**,導致資料洩露或錯誤。除非 100% 確定上下文不變,否則寧選 Context-Sensitive。
適用場景:多張表(如 SAVINGS、CHECKING)共用同一策略函數,且上下文相同。
機制:跨物件共用謂詞快取,避免切換表時重複執行函數。
policy_type => DBMS_RLS.SHARED_CONTEXT_SENSITIVE
policy_type => DBMS_RLS.SHARED_STATIC
DBMS_RLS.ADD_POLICY 的 SEC_RELEVANT_COLS 與 SEC_RELEVANT_COLS_OPT 實現「列級掩碼」而非行級過濾。DBA_POLICIES、V$VPD_POLICY 監控策略命中率與執行耗時。VPD 是 Oracle 資料庫層面實現行級安全的利器,關鍵在於**根據謂詞動態程度選對策略類型**。「動態」最安全但最慢,「靜態」最快但風險最高,「上下文敏感」是黃金平衡點。架構師應在設計階段即規劃上下文命名空間與策略分類,而非事後補丁。