Jeg vil anbefale, at du søger efter info på PostgreSQL-mailinglisterne om design med flere lejere. Der har været masser af diskussion der, og svaret koger ned til "det kommer an på". Der er afvejninger på alle måder mellem garanteret isolation, ydeevne og vedligeholdelse.
En almindelig tilgang er at bruge en enkelt database, men et skema (navneområde) pr. kunde med den samme tabelstruktur i hvert skema plus et delt eller fælles skema for data, der er ens på tværs af dem alle. Et PostgreSQL-skema er som en MySQL-"database", idet du kan forespørge på tværs af forskellige skemaer, men de er som standard isoleret. Med kundedata i separat skema kan du bruge search_path
indstilling, normalt via ALTER USER
customername SET search_path = 'customerschema, sharedschema'
for at sikre, at hver kunde ser deres data og kun deres data.
For yderligere beskyttelse bør du REVOKE
ALL FROM SCHEMA customerschema FROM public
derefter GRANT
ALL ON SCHEMA customerschema TO thecustomer
så de er den eneste, der har adgang til det, og gør det samme ved hvert af deres borde. Din forbindelsespulje kan derefter logge ind med en fast brugerkonto, der har ingen GRANT
ed adgang til ethvert kundeskema, men har ret til at SET ROLE
at blive en hvilken som helst kunde. (Gør det ved at give dem medlemskab af hver kunderolle med NOINHERIT sæt, så rettigheder skal eksplicit gøres krav på via SET ROLE
). Forbindelsen skal straks SET ROLE
til den kunde, det i øjeblikket fungerer som. Det vil give dig mulighed for at undgå omkostningerne ved at oprette nye forbindelser for hver kunde, samtidig med at du opretholder en stærk beskyttelse mod programmørfejl, der fører til adgang til den forkerte kundes data. Så længe puljen laver en DISCARD ALL
og/eller en RESET ROLE
før du deler forbindelser ud til den næste klient, vil det give dig en meget stærk isolation uden frustrationen af individuelle forbindelser pr. bruger.
Hvis dit webapp-miljø ikke har en anstændig forbindelsespulje indbygget (f.eks. du bruger PHP med vedvarende forbindelser), så er du virkelig nødt til at sætte en god forbindelsespulje
på plads mellem Pg og webserveren alligevel, fordi for mange forbindelser til backend vil skade din ydeevne. PgBouncer
og PgPool-II
er de bedste muligheder, og kan nemt tage sig af at udføre DISCARD ALL
og RESET ROLE
for dig under aflevering af forbindelse.
Den største ulempe ved denne tilgang er overheaden med at opretholde så mange tabeller, da dit basissæt af ikke-delte tabeller er klonet for hver kunde. Det vil stige, efterhånden som kundetallet vokser, til det punkt, hvor det store antal tabeller, der skal undersøges under autovakuumkørsler, begynder at blive dyrt, og hvor enhver operation, der skaleres baseret på det samlede antal tabeller i DB'en, bliver langsommere. Dette er mere et problem, hvis du tænker på at have mange tusinde eller titusindvis af kunder i samme DB, men jeg stærkt anbefaler, at du laver nogle skaleringstest med dette design ved hjælp af dummy-data, før du forpligter dig til det.
Den ideelle tilgang vil sandsynligvis være enkelte tabeller med automatisk række-niveau-sikkerhed, der kontrollerer tuple-synlighed, men det er desværre noget, PostgreSQL ikke har endnu. Det ser ud til, at det er på vej takket være SEPostgreSQL-arbejdet, der tilføjer passende infrastruktur og API'er, men det er ikke i 9.1.