Comments 46
Ага. Интересная штука… хоть я как вы уже наверно догадались, с недавних пор не очень люблю MySQL :)
Это все после посещения Хайлоада. :)
А точнее после лекции Петра Зайцева, не в упрёк ему будет сказано.
Лекция была интересная, но я сделал для себя вывод что MySQL подходит для большого круга задач но при этом эти задачи очень просты.

Если мы пишем что то большое MySQL предоставляет не очень много средств для того что бы упростить нам жизнь. Любой DBA напишет вам с десяток примеров когда MySQL показывает свою несостоятельность.
Но опять же, это всего лишь моё мнение. Каждый в праве использовать то что ему нравится и, самое главное, то в чём он лучше разбирается.
Призываю всех, всё таки не разжигать дискуссий на тему «MySQL vs PostgreSQL».
в mysqlnd( php ) есть возможность проксировать запрос «куда надо» через надстройку mysqlnd
те без внешних утилит, просто на усмотрение скрипта
Ой боюсь какбэ топик не перерос в противостояние адептов PostgreSQL и MySQL. :)
Обе хороши, при желании можно найти серьёзные проекты и на PostgreSQL и на MySQL.
Статья очень интересная, понравилась.
За статью спасибо, только грамматические ошибки глаз режут :).

По сути — если на каждой ноде лежат уникальные данные, то надёжность всей базы обратно пропорциональна кол-ву нод.
Как быть если одна из нод вышла из строя?
Есть ли какие-то средства восстановления целостности данных, и будет ли система вообще работоспособна при выключении какой-то из ноды?
По поводу ошибок — пишите же сюда. Я всё исправлю.
У меня, к сожалению, OpenOffice почему-то отказывается проверять ошибки после некоторого количества текста. Странный глюк.
По поводу выхода из строя.
Я думаю параллельно надо разворачивать реплицирующую базу данных. Ну и рэйды какбы тожне должны снизить риск.
Ну и о надёжности:
Как раз наоборот.

Предположим у меня 1 сервер. Что то на нём падает и всё. Весь сайт лежит.
Предположим у меня 5 серверов из которых 1 прокси.
Если упадёт одна из нод — то на сьйте просто не будут доступны те данные которые были расположены на этой ноде. А все остальные ноду будут работать и часть пользователей удасться обслужить.
Тут как раз помог бы ответ на мой вопрос: «Будет ли система вообще работоспособна при выключении какой-то из нод». Проведены ли подобные «крэштесты» на кластерах работающих под реальной нагрузкой? Это ведь самый критичный и распространённый кейс любого кластера, о котором в статье ни слова.

Если с этим проблем нет — тогда вы отчасти правы, в некоторых ситуациях надёжность будет действительно выше, но не во всех.

Если, например, данные распраделены по нодам, как бы это сказать, «не однородно», или для работы сервиса нужна агрегация данных, или сервис интенсивно использует целостность данных, или и т.д. — то выход из строя одной ноды будет приводить к НЕПРАВИЛЬНОЙ работе системы, люди будут видеть не верные данные и возможно совершать на их основе не верные действия, а это часто гораздо хуже чем просто временный отказ всей системы.

Согласен на все сто. Для этого надо устраивать такие вот краш-тесты.
В данный момент я как раз занимаюсь проектированием довольно большой системы и планирую применять PL/Proxy. Естественно перед тем как использовать будем проверять и устраивать тестирование на предмет отказа.
Думаю что материала на статью на собирается :)
Решению вопроса масштабируемости в этой статье как ни парадоксально, было отведено совсем мало места. Ну а про надежность такого решения речь как бы совсем не шла (и это правильно, поскольку это задача немного другого характера). Так вот, если рассмотреть представленую архитектуру, действительно получается, что каждая нода содержит некие уникальные данные, которые по хорошему должны быть защищены, если речь идет о высоконадежной системе. Поэтому для решения этой задачи понадобится делать реплицирующие сервера, на каждый существующий сервер, с возможным резделением ролей на Master-Slave\Master для оптимизации производительности. Еще одной single point of failure является сервер, на котором крутится PL/Proxy и PGBouncer, которую тоже неплохо было бы продублировать. И речь тут еще не идет о самом бизнес приложении, которое эту базу использует. Таким макаром получаем целый зоопарк дорогостоящего оборудования, который не каждая компания может себе позволить. Как результат разработчики высоконагруженых\кластерных систем выбирают для себя наиболее приемлимый уровень надежности, по соотношению цена\качество.
Спасибо, интересно, поскольку сам работаю с высоконагружеными серверами (и там чаще Postgresql используется). Значит PgBouncer увеличит производительность, даже если сервер Postgresql будет один?
И ещё — какой метод вы юзали в примере? Session Pooling, Transaction Pooling или Statement Pooling? И что посоветуйте?
Для PL/Proxy можно использвать только Statement Pooling.
А если сервер один то надо экспериментировать и смотреть на сколько много в системе транзакций.
Ну и конечно лучше об этом почитать на сьайте PgBouncer. :)
>>А если сервер один то надо экспериментировать и смотреть на сколько много в системе транзакций.

Например чат (веб старница, которая каждые 3 секунды делает запрос в бд на новые сообщения). Запросов много.

>>Ну и конечно лучше об этом почитать на сьайте PgBouncer
Спасибо, уже читаю
>> Например чат (веб старница, которая каждые 3 секунды делает запрос в бд на новые сообщения). Запросов много.

Под транзакциями я понимаю именно «транзакции» а не запросы к базе данных. В вашем случае я думаю транзакций нет и можно юзать Session Pooling.

Но всё таки лучше почитать что бы удостоверится :)
PgBouncer — единственный адекватный connection-pooler для postgresql. По собственному опыту настоятельно рекомендую — абсолютно стабильная вещь и работает как часы.

Правда производительности он особо не добавляет (разве что — сокращение времени соединения с сервером), но позволяет сократить использование ресурсов системы за счёт очень значительного сокращения количества postgresql-процессов.

Я считаю, что правильнее всего использовать метод Session Pooling — от греха подальше — так есть гарантия, что не нарвётесь ни ни какие коллизии.
Не понятно только как выборки делать в таком случае. Предположим нам нужно вывести _вторую_ страницу по пользователям отсортированным по дате создания и лимитом 10?
Элементарно Ватсон :)

Создаём функцию:

CREATE OR REPLACE FUNCTION plproxy.get_user_list(u_order text, limit_start int, limit_count int)
RETURNS SETOF text AS
$BODY$
CLUSTER 'clustertest';
RUN ON hashtext(i_username);
SELECT * FROM plproxy.users order by u_order limit limit_start, limit_count;
$BODY$
LANGUAGE 'plproxy' VOLATILE
COST 100
ROWS 1000;
Вообще при таком подходе все SQL-запросы мигрируют в базу в виде функций.
А в коде мы только вызываем их: select get_user_list(«user_date_create», 10*(1), 10);
ааа… я понял вопрос… Данные то распределены по шардам… ммм… вот тут надо подумать :)
Знач можно делать вот так:
там где у нас RUN ON hashtext(i_username);

Пишем:
RUN ON ALL;

Както так.
:) «как то так» конечно несколько не понятно, что происходит если мы запустим это на всех шардах. Данные каким то образом агрегируются и сортируются? А если у вас уже все работает может попробуете и поделитесь результатами.
работает :)
Код функции выглядит так:

CREATE OR REPLACE FUNCTION plproxy.get_users()
RETURNS SETOF text AS
$BODY$
CLUSTER 'clustertest';
RUN ON ALL;
SELECT email FROM plproxy.users;
$BODY$
LANGUAGE 'plproxy' VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION plproxy.get_users() OWNER TO postgres;

Данные агрегируются.
Вопрос по поводу сортировки остаётся открытым, и надо будет сортировать и лимитировать уже пришедшие с шардов данные.
Как это делать я представляю пока очень отдалённо так как не являюсь знатоком PL.
Так вот этот вопрос пожалуй самый актуальный. На HL++ тоже был, интересно было послушать.
Ойда. Если ещё например вспомнить про питон и Django там вроде как тоже есть что-то подобнее. Но вот для PHP, я так думаю, такое решение будет побыстрее чем если бы тоже самое реализовывать на самом php.
> Но вот для PHP, я так думаю, такое решение будет побыстрее чем если бы тоже самое реализовывать на самом php.
pardon?
Я имел ввиду что реализация шардинга средствами приложения на php была бы медленнее чем релизация на уровне базы данных.
хм, быстрее в человеко-часах? или быстрее выполнение запроса?
если первое — тут готовое решение выигрывает, и не нужно писать сложные (и трудно поддерживаемые) PL функции для каждой операции, причем добавить сервер дешевле (окупается за месяц-два), чем нанимать отдельного человека на адаптацию и поддержку
если второе, то что мешает сделать простейший шардинг, например разделяя записи по диапазону какого-то поля или вычисляя остаток отделения от PK? (кстати pl/sql компилируется в байт код?)

сказать сложно что будет быстрее выполнятся — надо проводить бенчмарки
UFO landed and left these words here
А чего сложного то?
Если используется MVC то весь SQL в одном месте и такой перенос даже для большого проекта займёт 1 день. При этом человек который это будет делать может даже не знать что за проект и как оно работает.

Ну и ещё Бизнесс логика она ж в Application Layer. И в моих примерах её нигде нет. Только выборки данных.
UFO landed and left these words here
>>> Связи между «MVC» и «весь SQL в одном месте» решительно никакой нет.
эээ… Вы забыли о чём спросили выше. Речь шла не про связь между этими фактами. А о том «легко или тяжело переносить SQL код из приложения в базу данных».
Но если чесно я усматриваю в ваших словах скрытую неприязнь ко всем php-программистам.

>>> Плюс к этому, потребуется чудовищная работа по переделыванию ORM слоя на хранимые процедуры.
О. ДОшли до ОРМ.
Всё зависит от фреймворка. В том который используется мной, это проблем не составляет.

Вы не верите что это легко? Я цифру в 1 день взял не с потолка ;)
UFO landed and left these words here
Чорд… Ну тогда я вас убедить не смогу.

Ну и ещё. Почему мы думаем что приложение надо будет «переводить на новую структуру»?
Надо его проектировать таким образом изначально. Нигде установок на «все быстренько ринулись переписывать все свои проекты за 1 день» не было. :)

А то что уже работает — врядли кто то будет переписывать.
С официального сайта Pg/Boucner https://developer.skype.com/SkypeGarage/DbProjects/PgBouncer:

PL/Proxy launches connections into each part from each backend, so in heavy-duty environment is necessary to put pooler between PL/Proxy and partitions.

А у вас на схеме Pg/Bouncer стоит над PL/Proxy. Это ошибка, или я не прав?
Ойойой. Это действительно ошибка.
Но не такая страшная как может показаться на первый взгляд.
Фактически pgBouncer нужен и там и там.
Другое дело что я когда писал я не правильно понял эту фразу. И думал что решаю проблему для таких вот heavy-duty enviroments устанавливая боунсер _перед_ прокси.

Даже и не знаю что делать.
Ведь если изменить схему то надо будет еще и переписать часть статьи. Но в таком варианте — она тоже верна. Буду надеятся что народ читает комментарии. Добавлю хедер сслыку на ваш комментарий.
Как можно заметить по рейтингу комментариев, читают в основном те комментарии, которые вначале. Тем более статья месячной давности. Я думаю, что для начала, в самом начале статьи стОит жирным, или даже красным, обратить внимание на ошибку.
Столкнулся с такой неприятностью, касательно заметки насчет sequence'ов.
Так как базы-ноды не могут генерировать sequence, им его нужно передавать (в insert-функциях). Соответственно должен быть дополнительный аргумент со значением sequence.

В базе-прокси определение функции должно быть таким же, как и в нодах (а именно, кол-во аргументов). То есть в соответствующей функции, в базе-прокси будет лишний аргумент sequence.

Приложение же не знает этого sequence, и не должно его знать, то есть оно должно выполнять функцию без аргумента sequence. Получается, что для каждой функции в базе-прокси, написанной на PL/proxy необходимо делать враппер на другом PL языке, который будет принимать n-1 аргумент, брать номер sequence, и выполнять функцию на языке Proxy уже с n аргументами? Есть идеи на этот счет?
ммм… я вот все еще не силен в PL
Но мне кажется что должна быть возможность вызывать любую функцию нода с любым количеством аргументов из прокси-функции.
Функции на прокси могут работать со всей базойданных самого прокси, т.е и использовать сиквенсы этой базы. Вот эти сиквенсы и предполагается использовать.
Это первый вариант — но надо ковырять что бы проверить так ли это. Мне очень жалко что я не могу удалить этому вопросу много времнени — начался большой проект и я не могу поковыряться всласть :)

Второй вариант — это использовать UUID www.postgresql.org/docs/8.3/interactive/datatype-uuid.html (новый тип данных с 8.3) вместо int для ID в базе. Генерировать его надо будет на стороне приложения так как пока в постгресе нет средств генерации :( Но он будет уникальным с очень большой степенью вероятности. Соответственно необходимость в сиквенсах отпадет.

У меня такая проблема.
Сделал как в примере, но постоянно получаю такую ошибку:

# select plproxy.get_user_email('Steve');
ERROR: Pl/Proxy: cluster not found: clustertest

У кого есть какие соображения по этому поводу?
Only those users with full accounts are able to leave comments. Log in, please.