Данная писанина объясняет как конфигурировать кластер PostgreSQL с использованием PL/Proxy. Приступим сразу к мат. части.
PL/Proxy может быть использован в режиме CONNECT или CLUSTER.
В режиме CONNECT PL/Proxy выступает в роли прозрачного проксирующего элемента к другой базе данных. Каждая функция PL/Proxy содержит строку соединения к другой базе данных для библиотеки libpq. При выполнении функции на текущем сервере, все операции будут физически происходить на удаленном сервере.
PL/Proxy также может быть использован в режиме CLUSTER. В режиме кластера PL/Proxy предоставляет поддержку порционирования данных на множестве серверов баз данных.
Когда используется режим CONNECT не требуется никаких специальных конфигураций. Однако, при использовании режима CLUSTER требуется настройка кластеров с помощью API кластеров или SQL/MED.
API конфигурирование кластера
Следующие функции используются для конфигурирования кластера с использованием PL/Proxy:
plproxy.get_cluster_version(cluster_name text)
returns integer
Функция plproxy.get_cluster_version вызывается при каждом запросе. Данная функция должна возвращать версию каждого кластера текущей конфигурации. Если функция возвращает число типа Целое и оно больше, чем число, которое было в кэше plproxy, то конфигурация и информация о кластере будет получены заново из функций get_cluster_config() и get_cluster_partitions().
Вот простой пример реализации функции get_cluster_version():
CREATE OR REPLACE FUNCTION plproxy.get_cluster_version(cluster_name text)
RETURNS int4 AS $$
BEGIN
IF cluster_name = 'a_cluster' THEN
RETURN 1;
END IF;
RAISE EXCEPTION 'Unknown cluster';
END;
$$ LANGUAGE plpgsql;
plproxy.get_cluster_partitions(cluster_name text)
returns setof text
Функция вызывается, когда необходимо получить конфигурацию партиций кластера. Она должна возвращать строку соединения с партициями кластера. Строки соединения должны быть возвращены в правильном порядке. Количество возвращаемых строк соединения должно быть кратно двум. Если две или более строк идентичны (указывают на соединение с одним и тем же кластером) то будет использовано одно соединение. Данная функция полезна, если у вас количество партиций не кратно двум. Ну в самом деле, не покупать же еще один сервер если он не нужен.
Если в возвращаемой строке соединения не фигурирует параметр "user=", то будет использован текущий пользователь (user=CURRENT_USER) для соединения с партицией. Использование "рутового" пользователя postgres запрещено.
Несколько советов о том, как передавать пароли для соединения:
- Храните пароли в файлах .pgpass / pg_service.conf. Данный прием вполне безопасен. Единственное неудобство в том, что Вы не сможете изменить пароли непосредственно из базы данных. Вам нужно будет редактировать эти файлы.
- Загружайте пароли из таблиц/файлов и передавайте их в строке соединения. Есть прокол в безопасности. Пользователи СУБД смогут увидеть эти пароли.
- Используйте один пароль для всех пользователей и передавайте его в строке соединения. Данный способ опасен в двойне. Пользователи СУБД могут увидеть пароль со всеми вытекающими.
- Используйте авторизацию с помощью пулера (Pooling), который слушает соединения только на локальной машине или еще лучше на UNIX SOCKET. Это отличная комбинация. Так как при установке PgBouncer вы получаете в свой кластер Connection Pooling + PgBouncer умеет считывать пароли непосредственно из файлов безопасности PostgreSQL (pg_auth) и использовать их для открытия соединения с вашими партициями.
- Использовать доверенное соединение с партициями. Откровенно плохая идея.
Пример функции get_cluster_partitions при хранении каждой из таблиц в разных партициях:
CREATE OR REPLACE FUNCTION plproxy.get_cluster_partitions(cluster_name text)
RETURNS SETOF text AS $$
BEGIN
IF cluster_name = 'a_cluster' THEN
RETURN NEXT 'dbname=part00 host=127.0.0.1';
RETURN NEXT 'dbname=part01 host=127.0.0.1';
RETURN NEXT 'dbname=part02 host=127.0.0.1';
RETURN NEXT 'dbname=part03 host=127.0.0.1';
RETURN;
END IF;
RAISE EXCEPTION 'Unknown cluster';
END;
$$ LANGUAGE plpgsql;
plproxy.get_cluster_config(in cluster_name text,
out key text, out val text)
returns setof record
Функция get_cluster_config() возвращает массив типа ключ=значение. Все ключи опциональны и не обязательны. Временные параметры задаются в секундах. Если значение 0 или NULL, то это означает что параметр отключен и будет использовано значение по умолчанию.
- connection_lifetime - Максимальное время жизни соединения к удаленной базе данных, которое будет постоянно открыто. Если значение не установлено, то соединение будет длиться столько, сколько будет оставаться.
- query_timeout - Если запрос не дает результат, указанное в этой опции время, то соединение закрывается. Если этот параметр установлен, то на удаленном сервере должен быть установлен параметр statement_timeout и обязательно установлен в меньшее значение чем query_timeout.
- disable_binary - Не использовать бинарный ввод/вывод для этого кластера.
- connect_timeout - Если соединение не открылось за отведенное время, то оно не открывается.
Пример функции:
CREATE OR REPLACE FUNCTION plproxy.get_cluster_config(
in cluster_name text,
out key text,
out val text)
RETURNS SETOF record AS $$
BEGIN
-- будем использовать один и тотже конфиг для всех кластеров
key := 'connection_lifetime';
val := 30*60; -- 30m
RETURN NEXT;
RETURN;
END;
$$ LANGUAGE plpgsql;
Определение кластеров с помощью SQL/MED
В PostgreSQL 8.4 и выше можно настроить кластеризацию PL/Proxy при помощи SQL/MED. Весь перчик в том, что SQL/MED - это упрощенный механизм настройки кластеров который гараздо производительнее предыдущего метода (определением функций).Оба метода определения кластров могут сосуществовать в одной базе данных вместе в один и тотже момент времени. Но тогда будет действовать следующее правило: Если информация о кластере не существует в SQL/MED, то она будет запрошена с помощью функций.
Конфигурирование SQL/MED кластеров.
Во первых нам нужно создать внешний враппер данных (ВВД). В целом ВВД - это драйвер, обеспечивающий доступ к удаленным базам данных, их маршалинг и прочее. В нашем конкретном случае роль ВВД сводится к валидации параметров доступа к кластерам.
ВНИМАНИЕ: Функция валидации была испорчена во всех версиях ниже PostgreSQL 8.4.2. По этому обновитесь до более высокой версии перед ее использованием.
CREATE FOREIGN DATA WRAPPER plproxy [ VALIDATOR plproxy_fdw_validator ];
Далее нам нужно определить кластер. Данный этап можно считать завершенным после создания PostgreSQL сервера, который использует plproxy ВВД. Опции SERVER и список партиций фактически являются настройками конфигурации PL/Proxy. И будут использованы PL/Proxy для работы.
ВНИМАНИЕ: Использование SERVER должно быть разрешено тем пользователям, которые будут работать с кластером. Иначе ничего не получится.
CREATE SERVER a_cluster FOREIGN DATA WRAPPER plproxy
OPTIONS (
connection_lifetime '1800',
disable_binary '1',
p0 'dbname=part00 hostname=127.0.0.1',
p1 'dbname=part01 hostname=127.0.0.1',
p2 'dbname=part02 hostname=127.0.0.1',
p3 'dbname=part03 hostname=127.0.0.1'
);
Финальным шагом будет создание маппинга пользователей на пользователей PL/Proxy. Для каждого пользователя базы данных нужно создать отдельный маппинг. Делается это так:
CREATE USER MAPPING FOR bob SERVER a_cluster
OPTIONS (user 'bob', password 'secret');
или создайте публичный маппинг для всех пользователей:
CREATE USER MAPPING FOR public SERVER a_cluster
OPTIONS (user 'plproxy', password 'foo');
Также можно создавать индивидуальные и публичные маппинги вместе.
Мануал актуален на 2010-01-11 11:52:40.
По большому счету является переводом официальной документации PL/Proxy. Написан как пособие для рускоязычных пользователей чтобы лучше понимать процесс конфигурации кластера с использованием PL/Proxy. Буду благодарен за любые дополнения и исправления.

Комментировать