深入探討:多租戶實體關係圖設計的細微之處

為多租戶環境設計穩健的資料庫結構,與單租戶架構相比,需要根本性的思維轉變。當多個客戶(租戶)共用相同的基礎設施時,實體關係圖(ERD)便成為資料隔離、安全與效能的藍圖。🏗️ 設計不良的ERD可能導致資料外洩、效能下降,以及複雜的遷移路徑。本指南探討在不依賴特定軟體工具的情況下,建模多租戶系統的結構細節,重點放在架構原則上。

Hand-drawn infographic illustrating multitenant Entity Relationship Diagram design principles: comparing three isolation models (database per tenant, schema per tenant, shared schema), showing ERD best practices including tenant_id columns, foreign key relationships, indexing strategies, security measures like row-level security, and a checklist of key considerations for building secure, scalable multitenant database architectures

理解共用資料的核心挑戰 🏢

在傳統的單租戶設定中,每位客戶都擁有自己獨立的資料庫。應用程式與資料之間的關係是一對一。然而,在多租戶系統中,關係則是一對多。應用程式從共用資源池中為多個租戶提供服務。ERD必須明確地將租戶的上下文編碼到每一筆查詢與交易中。

主要目標是確保租戶A永遠不會看到屬於租戶B的資料,即使他們查詢的是完全相同的資料表。這通常被稱為邏輯隔離。ERD必須透過資料結構設計原生支援此種隔離,而非僅依賴應用程式邏輯。🔒

隔離模型及其對資料結構設計的影響 🏗️

有三種主要的租戶資料隔離模型。每種模型都決定了實體關係圖截然不同的設計方式。在設計初期選擇錯誤的模型,後續將被迫進行成本高昂的重寫。

1. 每租戶一個資料庫(物理隔離)

在此模型中,每位租戶都擁有自己的物理資料庫實例。ERD與單租戶設計完全相同。每個資料表都獨立存在於各自的資料庫容器中。

  • 優點:安全性與隔離程度達到最大。租戶之間的資料外洩在物理上不可能發生。
  • 缺點:營運成本高。管理數百甚至數千個資料庫相當複雜。
  • 資料結構影響:ERD無需考慮租戶識別欄位,因為資料庫本身即為識別依據。

2. 每租戶一個資料結構(邏輯隔離)

多位租戶共用單一資料庫,但每位租戶在該資料庫內擁有自己獨立的資料結構(命名空間)。ERD與單租戶版本大致相同,但資料結構名稱會根據租戶而變更。

  • 優點:比共用資料表具有更好的隔離性。管理上比單獨的資料庫更簡單。
  • 缺點:查詢複雜度增加,因為應用程式必須動態切換資料結構。
  • 資料結構影響:ERD無需在每個資料表中加入租戶ID欄位。相反地,由資料庫連接的上下文來處理分離。

3. 共用資料結構,共用資料表(邏輯隔離)

這是SaaS應用程式中最常見的模型。所有租戶共用完全相同的資料表。ERD必須進行修改,以在每一筆相關資料列中加入每位租戶的唯一識別碼。

  • 優點:成本最低,營運開銷最小。執行全域分析更為容易。
  • 缺點:若邏輯失敗,資料外洩風險最高。隨著資料表規模擴大,效能可能下降。
  • 資料結構影響: 每個表格都必須包含一個 tenant_id 欄位。外鍵必須參考此欄位以維持完整性。

設計共用架構的ERD 🔑

採用共用架構模型時,ERD需要進行特定修改,以確保資料完整性和安全性。本節將詳細說明您的圖表中必須包含的關鍵元件。

租戶識別欄位

所有儲存使用者特定資料的表格都必須包含一個欄位,用以識別該資料的所有者。此欄位通常命名為tenant_idorganization_id.

  • 資料類型: 應為整數或UUID。整數在連接操作中通常更快。
  • 不可為空約束: 此欄位永遠不應允許為空。空值表示資料無主,這違反了多租戶合約。
  • 預設值: 在某些應用程式中,預設值可能在應用程式層級設定,但資料庫架構應強制要求此值存在。

外鍵關係

當表格彼此相關時,關係必須尊重租戶邊界。一個常見錯誤是建立全域表格(如產品目錄)與租戶特定表格(如訂單)之間的關係。

  • 全域表格:ProductsCategories 可能被共用。它們不需要 tenant_id.
  • 租戶表格:Orders使用者 必須具有 tenant_id.
  • 合併邏輯: 當將全域資料表與租戶資料表合併時,合併條件必須包含 tenant_id 以防止跨租戶資料外洩。

比較隔離策略 📊

理解權衡關係對於選擇正確的ERD結構至關重要。下表概述了主要隔離策略之間的主要差異。

策略 隔離層級 成本 管理複雜度 結構需求
每個租戶一個資料庫 物理 標準(無租戶ID)
每個租戶一個結構 邏輯 中等 中等 標準(結構名稱)
共用結構 資料列層級 需要租戶 ID 欄位

ERD 設計中的效能考量 🚀

隨著資料累積,共用結構的效能可能會下降。ERD 必須支援能針對租戶特定查詢進行最佳化的索引策略。

索引策略

若沒有適當的索引,用來取得單一租戶資料的查詢可能會掃描整個資料表,其中包含來自其他租戶的數百萬筆資料。

  • 複合索引:建立以 tenant_id為起點的索引。例如,在 (tenant_id, created_at) 上建立的索引,可讓資料庫快速定位特定租戶的記錄並進行排序。
  • 覆蓋索引: 若您經常查詢特定欄位,請將這些欄位包含在索引中,以避免資料表查找。
  • 分割:大型資料表可依 tenant_id進行分割。這會在磁碟上物理性地分離資料,提升查詢速度並改善備份管理。

查詢最佳化

應用層必須確保每個查詢都包含 tenant_idWHERE子句中。ERD 設計不應依賴應用程式來過濾資料;資料庫應為唯一真實來源。

  • 資料列層級安全性: 某些資料庫系統支援資料列層級安全性(RLS)。ERD 可利用此功能,根據已驗證使用者的上下文自動過濾資料列。
  • 查詢計畫:定期檢視查詢執行計畫。確保資料庫正在使用 tenant_id 索引且不執行完整表格掃描。

安全與合規性影響 🛡️

資料隱私法規(如GDPR和CCPA)對資料的儲存與存取方式設有嚴格要求。ERD在合規性方面扮演著關鍵角色。

資料隔離

合規性通常要求資料能輕易分離。若租戶要求刪除其資料,系統必須能定位並移除與其相關的所有記錄。tenant_id.

  • 軟刪除: 不直接硬性刪除資料列,而是標記為已刪除。這通常對審計更安全。deleted_at 欄位也應根據 tenant_id.
  • 加密: 租戶範圍內的敏感欄位應予以加密。金鑰管理策略必須與租戶隔離模型一致。

審計與記錄

審計追蹤對於安全至關重要。對租戶資料所執行的每一項操作都應被記錄。

  • 審計表格: 建立專用的記錄表格,其中包含受影響實體的 tenant_id 所屬實體。
  • 存取控制: 確保審計記錄本身受到保護。管理員不應能查看其未管理租戶的審計記錄。

結構演進與遷移 🔄

應用程式不斷演進,功能被新增,資料結構也會改變。在多租戶環境中,結構遷移更加複雜,因為必須在不造成停機或資料遺失的情況下,將變更套用至所有租戶。

向後相容性

修改ERD時,請確保維持向後相容性。

  • 新增變更: 若欄位允許空值,向資料表新增欄位通常是安全的。
  • 欄位移除: 這很危險。在確保沒有租戶使用該欄位並設立棄用期間後,才能刪除欄位。
  • 重新命名欄位: 這可能會導致查詢失效。最好新增一個欄位,遷移資料,再切換參考,而不是直接重新命名。

零停機遷移

對於大型租戶而言,在遷移期間鎖定表格並非可行方案。ERD 設計應支援線上結構變更。

  • 幽靈表格: 建立一個具有更新結構的新表格,複製資料,然後交換表格。
  • 版本控制: 某些系統支援同時存在多個結構版本,以實現逐步推出。

常見陷阱,應避免 ⚠️

設計多租戶 ERD 涉及許多變動部分。以下是一些會損害系統的常見錯誤。

  • 忽略租戶 ID: 忘記在開發期間建立新表格時加入 tenant_id 到新建立的表格中。這會立即帶來資料外洩的風險。
  • 硬編碼 ID: 永遠不要在應用程式程式碼中硬編碼租戶 ID。必須在執行時動態傳遞。
  • 全域計數器: 如果全域自動遞增計數器出現在 URL 或 API 回應中,應避免使用,因為這可能暴露租戶或使用者的數量。
  • 共用檔案: ERD 關注資料庫,但檔案儲存常被忽略。請確保檔案路徑包含租戶識別碼,以避免存取問題。

複雜情境的進階模式 🔍

並非所有多租戶系統都相同。有些系統需要對資料結構有更細緻的控制。

多組織支援

一個租戶可能屬於多個組織,反之亦然。ERD 必須支援多對多關係。

  • 關聯表格: 使用關聯表格來連結使用者、租戶與組織。
  • 權限模型: ERD 應支援租戶層級的角色權限控制(RBAC)。

全域設定與租戶特定設定

某些設定資料是全域的(應用程式範圍內),而其他資料則是特定於租戶的。

  • 設定表格:設計ERD以區分全域設定與租戶特定的覆蓋設定。
  • 繼承:租戶設定可能繼承自全域預設值。資料結構應明確反映此層級關係。

最佳實務總結 ✅

建立安全且可擴展的多租戶系統,很大程度上取決於實體關係圖所奠定的基礎。遵循以下原則,可確保長期穩定性。

  • 一致性:確保每個儲存使用者資料的表格都包含租戶識別碼。
  • 隔離:選擇符合您安全與成本需求的隔離模型。
  • 效能:設計以租戶識別碼為優先的索引。
  • 安全性:在適當情況下實施資料列層級的安全性與加密。
  • 可維護性:規劃不會中斷服務的資料結構變更。

您的資料庫結構設計是一項戰略性決策,影響應用程式的整個生命週期。良好的實體關係圖可防止資料外洩,確保合規性,並支援成長。在設計階段仔細考慮多租戶的細節,將建立一個具韌性且安全的基礎。 🏛️

隨著應用程式成長,持續檢視ERD是必要的。新功能經常引入新的資料關係,必須根據租戶隔離規則進行評估。保持警覺,記錄您的設計決策,並始終將資料完整性放在首位。這種做法可確保您的架構在擴展時仍保持穩健。