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

MySQL 實現動態視圖:透過 Session 變數與自訂函數實現多租戶資料隔離

     編輯:MySQL 資料庫相關知識

需求場景

C/S 架構應用,不同角色用戶查詢同一視圖但見到不同資料。要求:不修改視圖定義、不在外層包裝查詢。

設計思路

  1. 系統產生唯一識別 ID(應用端或 UUID())
  2. 將 ID 存入 Session 變數 @spid
  3. 建立自訂函數 getSpid() 回傳該變數
  4. 視圖 WHERE 條件呼叫 getSpid() 過濾資料

完整實作碼

1. 建立基礎表與測試資料

DROP TABLE IF EXISTS test;
CREATE TABLE test (
    id INT NOT NULL,
    name VARCHAR(20) NOT NULL
);

INSERT INTO test VALUES
(1, 'test1'), (1, 'test11'), (1, 'test111'),
(2, 'test2'), (2, 'test22');

2. 建立取得 Session 變數的函數

DROP FUNCTION IF EXISTS getSpid;
DELIMITER |
CREATE FUNCTION getSpid()
RETURNS INT
RETURN @spid;
|
DELIMITER ;

3. 建立動態視圖

DROP VIEW IF EXISTS v_test;
CREATE VIEW v_test AS
SELECT * FROM test WHERE id = getSpid();

4. 測試驗證

-- Session 1:用戶 A
SET @spid = 1;
SELECT * FROM v_test;
-- 結果:test1, test11, test111

-- Session 2:用戶 B
SET @spid = 2;
SELECT * FROM v_test;
-- 結果:test2, test22

原理解析

元件作用
@spidSession 級用戶變數,連線隔離,互不干擾
getSpid()確定性函數,包裝變數讀取,供視圖呼叫
v_test視圖定義固定,執行時動態帶入當前 Session 的 @spid

應用擴展

  • 多租戶 SaaS:@tenant_id 隔離客戶資料
  • 資料權限控制:@role_id 配合權限表過濾
  • 軟刪除過濾:@show_deleted 控制是否顯示已刪除資料

注意事項

  • 函數必須宣告 DETERMINISTIC 或 READS SQL DATA(MySQL 8.0+ 預設嚴格檢查)
  • 視圖中呼叫函數可能影響查詢優化器判斷,大數據量需測試效能
  • 連線池環境下需確保每次請求正確設定 Session 變數(如連線取得後立即 SET @spid = ?)
  • 替代方案:MySQL 8.0 ROW_LEVEL_SECURITY、MariaDB SECURITY POLICY 原生支援行級安全
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved