Как разделить таблицу между несколькими базами данных Postgresql - PullRequest
13 голосов
/ 27 ноября 2011

Мое веб-приложение имеет несколько развертываний - каждое из них является уникальным сайтом с уникальным URL.
Каждое развертывание имеет разные данные, пользовательский интерфейс и т. Д., Но очень похожую структуру базы данных Postgresql (с PostGIS). Все базы данных живут на одном сервере БД. Я хотел бы, чтобы пользователи из 1 развертывания могли входить во все другие развернутые приложения без необходимости повторной регистрации.

То, что я хочу, - это одна таблица «пользователей», которая используется несколькими базами данных приложений. Любой пользователь, который регистрируется в одном приложении, должен распознаваться всеми другими приложениями. Это возможно с Postgres? Схемы - способ сделать это?

Ответы [ 3 ]

18 голосов
/ 27 ноября 2011

Да, схемы - это решение. Используйте один кластер PostgreSQL с одной базой данных.

Создать группу для всех пользователей приложения:

CREATE ROLE app;

Создание глобальной схемы «приложения», в которой будут жить все глобальные таблицы общих приложений.

CREATE SCHEMA AUTHORIZATION app;
CREATE TABLE app.objects ( objectid int PRIMARY KEY );
ALTER TABLE app.objects OWNER TO app;

Создание отдельного пользователя (без прав суперпользователя) для каждого из развертываний:

CREATE USER app01 IN ROLE app;
CREATE USER app02 IN ROLE app;

Дополнительно, вместо IN ROLE app, вы можете предоставить явные права этим пользователям на выбранные объекты приложения:

GRANT USAGE ON SCHEMA app TO app01;
GRANT SELECT on app.objects TO app01;

Создание частных схем, в которых будут находиться таблицы, зависящие от развертывания:

CREATE SCHEMA AUTHORIZATION app01; 
CREATE SCHEMA AUTHORIZATION app02;

Теперь у вас есть частная схема для каждого развернутого приложения; но в то же время у вас есть общий доступ к глобальным данным.

Что приятно, это то, что приложение не должно быть осведомлено о схеме. SELECT * FROM froobles по умолчанию преобразуется в SELECT * FROM app01.froobles, если вы подключены как app01 пользователь. Вам не нужно указывать имя схемы.

В качестве дополнительной меры вы можете использовать наследование таблиц для расширения глобальных объектов для каждого развертывания:

CREATE TABLE app01.objects (
  localattr1 int,
  localattr2 text
)
INHERITS ( app.objects );
4 голосов
/ 17 мая 2012

Ответ filiprem потрясающий .. Однако я обнаружил, что мне нужно было настроить пути и для пользователей app01, app02:

ALTER USER app01 SET SEARCH_PATH TO "$user",app;
ALTER USER app02 SET SEARCH_PATH TO "$user",app;

Также, если вам нужно, чтобыДля роли app для доступа к таблицам в схемах app01, app02 вам понадобится следующий код:

-- grant all future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA app01 GRANT SELECT ON TABLES TO app;

-- grant all existing tables
GRANT SELECT 
ON ALL TABLES IN SCHEMA app01
TO app

Вместо SELECT вы можете иметь другие привилегии.То же самое для пользователя app02.

Обновление: Для того, чтобы пользователь app мог выбирать строки в схеме app01, ему необходимы как минимум права USAGEдля схемы app01 (вместе с привилегией таблицы SELECT, определенной выше):

GRANT USAGE ON SCHEMA app01 TO app; 
2 голосов
/ 27 ноября 2011

Взгляните на dblink .

...