我建議搜索有關多租戶設計的PostgreSQL郵件列表信息。這裏有很多討論,答案歸結爲「取決於」。在保證隔離,性能和可維護性之間,每種方式都有權衡。
一種常見的方法是使用單個數據庫,但每個客戶使用一個schema(名稱空間),每個客戶在每個模式中具有相同的表結構,並且對於所有數據都是相同的數據使用共享或通用模式。 PostgreSQL模式就像一個MySQL「數據庫」,您可以跨不同模式查詢,但默認情況下它們是隔離的。通過獨立模式中的客戶數據,您可以使用search_path
設置,通常通過ALTER USER
customername SET search_path = 'customerschema, sharedschema'
來確保每位客戶都能看到他們的數據並且只能看到他們的數據。
對於額外的保護,您應該REVOKE
ALL FROM SCHEMA customerschema FROM public
然後GRANT
ALL ON SCHEMA customerschema TO thecustomer
所以他們是唯一一個與它的任何訪問,做同樣的每個其表的。連接池,然後可以與具有沒有向任何客戶模式GRANT
版訪問,但有SET ROLE
權,成爲客戶的任何一個固定的用戶帳戶登錄。 (這樣做是通過給予他們每個客戶角色的成員身份,使用NOINHERIT設置權限,因此權限必須通過SET ROLE
明確聲明)。連接應立即SET ROLE
到它目前正在運行的客戶。這將允許您避免爲每個客戶建立新連接的開銷,同時保持強大的保護,防止程序員錯誤導致訪問錯誤的客戶數據。只要該池在將連接移交給下一個客戶端之前執行DISCARD ALL
和/或RESET ROLE
,那麼這將給予您非常強大的隔離,而不會讓每個用戶的單獨連接受挫。
如果你的Web應用程序環境中沒有一個像樣的連接池內置的(比如,你正在使用PHP和持久連接),那麼你真的需要把good connection pool到位PG和Web服務器之間無論如何,因爲太多的後端連接會傷害你的表現。 PgBouncer和PgPool-II是最好的選擇,並且可以在連接切換時輕鬆地爲您做好DISCARD ALL
和RESET ROLE
的準備工作。
這種方法的主要缺點是維護很多表的開銷,因爲您爲每個客戶克隆了一組非共享表。隨着客戶數量的增長,它會相加,直到在自動清理運行期間檢查的表的數量開始變得昂貴,並且根據數據庫中的表總數進行縮放的任何操作變慢。如果您想要在同一個數據庫中擁有數千或數萬個客戶,那麼這更成爲一個問題,但我強烈建議您在提交之前使用虛擬數據對此設計進行一些縮放測試。
理想的方法很可能是使用自動行級安全控制元組可視性的單個表,但不幸的是,這是PostgreSQL尚不具備的。由於SEPostgreSQL的工作增加了合適的基礎架構和API,它看起來很順利,但它不在9.1中。
非常感謝! (對不起,最近一直在和MySQL一起工作,它讓我腦子死了。)模式應該是多個數據庫的選項 - 事實上,它已經用於其他項目。連接後設置角色的好主意。一直在使用set path,但是兩者的組合最好。 –
是的,設置角色讓您可以使用數據庫級別的安全性,而不會產生太多的痛苦。這很棒。 –
...並且記住要使用像PgPool-II或PgBouncer這樣體面的連接池,如果你在Web服務器端使用基本的東西,比如持久連接的PHP。如果您使用的是類似於Java服務器的服務器,並且它自己的連接池在服務器中,則不需要。 –