Pull to refresh

Comments 64

В MySQL есть еще такая забавная конструкция, как binlog_format = MIXED: как бы для детерминированных запросов пишется statement, иначе — row. Помню, что его в какой-то версии включили по умолчанию, но очень быстро это изменили :-) Выглядит как хак на хаке, но, тем не менее, я рискнул использовать в одном проекте, прежде всего, из соображений существенной в данном случае экономии сетевого i/o — пока что ничего не развалилось, тьфу-тьфу :)

О логической репликации как таковой (не считая сторонних извращений) в PostgreSQL говорить рано; logical decoding — это зачатки, и там многое еще не реализовано (тот же DDL). Уверен, что все будет — в постгресе обычно делают неспешно, но по уму.

Физическую репликацию в innodb очень хотелось бы увидеть — много кейсов, когда это ровно то, что надо, и row-бинлог выглядит действительно как вынужденное полное дублирование на пустом месте. Реализовать такое довольно просто, мне кажется. Конечно, innodb-only будет выглядеть хаком, но в случае с mysql одним хаком больше, одним меньше — несущественно :)
MIXED — это некий компромисс между «правильным», но избыточным ROW, и «кривым», но очень лёгким STATEMENT. Кому-то и это подойдёт, да, и у меня в черновике было предложение об этом. Но я не стал перегружать пост несущественными деталями и убрал.
да-да, была бы в мускуле физическая репликация для innodb, мы бы не стали кучу денег тратить и переходить на посгрес. Так что если Oracle сделает такую штуку для mysql, это будет огроменный плюс к базе
Вроде всё немного по другому с миксед. В роу пишутся изменения данных, а в стейтмент — изменения метаданных(схемы).
Вы не правы. Это в row пишутся изменения данных, а изменения метаданных всё равно в statement-виде.
То, что Вы описали выше — это не MIXED, а ROW-based format. Все DDL всегда пишутся в формате statement, независимо от формата логов. Ну в самом деле: какие могут быть изменения строк при изменении метаданных? MIXED работает именно так, как описал symbix
> Помню, что его в какой-то версии включили по умолчанию, но очень быстро это изменили :-)

Это в какой-то 5.1, кажется, было. Дело в том, что тогда это была новая фича и, естественно, не настолько стабильная как старый statement. Сейчас те баги уже давно устранили и MIXED безопасен.
Типичный кейс для веб-сайтов а-ля блог в конфигурации 1 мастер, много слейвов:
1) Пользователь отредактировал статью. Движок послал UPDATE в мастер и инвалидировал кэш веб-страницы с постом.
2) Пользователь (этот же или другой) зашёл на страницу с отредактированной статьей. Лвижок послал SELECT на один из слейвов и получил старые данные, потому что слейв еще не догнал мастера. Старые данные осели в кэше веб-страницы.
3) Пользователь не видит своих правок на странице, F5/Ctrl-R не помогают. Пользователь негодует.

В PostgreSQL это проблема легко решается включением синхронной репликации, а в MySQL как?
Добро пожаловать в мир распределённых систем. Если я правильно читаю документацию здесь синхронная репликация в PostgreSQL консистентности данных на слейве вам не гарантирует — они только гарантирует, что транзакция с мастера передана на слейв, но она может быть ещё не проиграна на момент SELECT. Да и это гарантировано только для одного слейва в каждый момент времени (текущий синхронный standby). Так что нет, это не спасёт в том случае, который вы описываете.

Но проблема консистентности в распределённых системах — это тема не для комментария под статьёй. Всё зависит от того, что именно нужно получить. Пользователь блога может негодовать, если получит неконсистентый ответ через минуту. А в течение нескольких секунд скорее и не заметит. А для какой-нибудь системы бронирования билетов консистентность нужна моментальная на всех узлах.

Этак мы тут щас к CAP-теореме придем. :)
Да, куда ж без неё. Хотя там мифов и легенд ещё побольше будет.
Можно подумать, что описанные случаи с SELECT/UPDATE — это проблема. Все программисты знают как с этим жить. :)
Можно подумать в мире мало криво написанных приложений ;)
По моему опыту, программисты склонны прислушиваться к советам DBA. А последние не склонны понижать производительность кластера странными «крутилками» :)
Расскажите это программистам из Тонлайн, разработчикам системы «СуперБилет».

Это к слову о системе заказа билетов. Там, например, есть шлюз SOAP, и после выполнения команды «выбрать билет для бронирования/покупки» можно было увидеть новый статус (командой «посмотреть статус») не ранее чем через 30 секунд… причём это было сделано намеренно. Зачем — не смогли объяснить. Слава богу, другой пользователь в это время это же место выбрать всё равно не мог (получал ошибку «место занято», хотя при запросе статуса оно выглядит как свободное), и слава богу, по запросу они убрали эту дебильную задержку.
Обычно полусинхронной перконой
Semisynchronous Replication не спасёт от описанного кейса если слейвов больше чем один это раз. И два слейв может отставать.
https://www.percona.com/doc/percona-xtradb-cluster/5.6/features/multimaster-replication.html
wsrep_causal_reads=ON.
Свет, эта опция не о том. Она не гарантирует консистентных с мастером результатов на слейве в описанном случае. Она позволяет регулировать консистентность данных после падения мастера — что приложения могут увидеть до подения мастера и после failover.
Полусинхронная репликация не решает эту проблему. Она не решается просто, хоть с MySQL, хоть с PostgreSQL. Есть Galera Cluster, но это для блогов может быть и перебором.

Есть умные балансировшики нагрузки, которые мониторят слейвы, и направляют на них запросы, только если они отстают не более чем на N секунд. Для блогов такого вполне бы хватило.
Почему не решает. Вы не сможете прочитать строку на которой еще не произведен commit на слейве. И, кстати, Percona использует галеру, точнее ее wsrep API.
Да, но я (или кэш, или балансировщик нагрузки) может пойти на слейв, и там этой строки не увидеть. Потому что соответствующая транзакция лежит в relay log (это гарантирует нам синхронная репликация), но ещё не проиграна. Вопрос был в этом. И синхронная репликация здесь не поможет. Ни в MySQL, ни в PostgreSQL.
dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_rpl_semi_sync_master_wait_point

AFTER_COMMIT: The master writes each transaction to its binary log and the slave, syncs the binary log, and commits the transaction to the storage engine. The master waits for slave acknowledgment of transaction receipt after the commit. Upon receiving acknowledgment, the master returns a result to the client, which then can proceed.

With AFTER_COMMIT, the client issuing the transaction gets a return status only after the server commits to the storage engine and receives slave acknowledgment. After the commit and before slave acknowledgment, other clients can see the committed transaction before the committing client.


Кажется вместе с sysvar_rpl_semi_sync_master_wait_for_slave_count можно добиться нормальной работы для бложиков и не бояться балансеров и прочего.
Вот здесь есть с картинками для наглядности: my-replication-life.blogspot.com/2013/09/loss-less-semi-synchronous-replication.html

Полусинхронная относится только к IO thread на слейве. Все опции управляют только тем, в каком порядке делать COMMIT на мастере — до подтверждения от слейва, или после. А сам слейв посылает подтверждение всегда после сохранении транзакции в relay log, а не после проигрывания.

Иными словам, полусинхронная репликация остаётся всегда полусинхронной, синхронную из неё никакими опциями не сделать. То, что в PostgreSQL называется синхронной, на самом деле синхронной не является в смысле консистентности данных между узлами. И полусинхронной она не является тоже. Это что-то промежуточное.
Ответ на «типичный кейс» может быть таким:
1. Храните у юзера в сесии (или куке, если вам везет и в проекте нет кроссдоменности) текущую позицию мастера на момент после последной записи данного конкретного юзера. Не пускайте юзера читать со слейва до тех пор, пока слейв не догнал мастер до позиции, которая сохранена у данного юзера в сессии/куке (не у «всех» юзеров, а у конкретного — потому что реплика никогда не догонит мастер для всех юзеров).
2. С инвалидацией кэша похуже, т.к. кэш может быть случайно заполнен другим юзером, пришедшим через полсекунды после апдейта первого. Ну что тут можно придумать… например, не инвалидировать кэш немедленно, а добавлять команду инвалидации данных в какую-то легкую табличку-очередь в той же самой базе, чтобы инвалидация происходила, только когда данные доехали до слейва. Может, есть какой-то другой стандартный способ решения?
А вот, кстати, для инвалидации кэша вполне подойдет logical decoding со слейва.
Спасибо за статью!
А вот можно реквестовать статью по настройке mysql/postgresql для ноды фиксированной памяти?
Давайте возьмём nginx+php-fpm+db_name.
Пускай размер php-fpm будет 20 и 80мб. Ну для «простых» фреймворков и «крутых». Просто два варианта рассмотрим.
Давайте рассмотрим инстансы для «маленьких» — 512, 1024, 2048, 4096.
Давайте примем за истину, что db_запросы занимают 70% времени работы php-скрипта.
Внмание вопрос — как правильно искать узкие места и оптимизировать их?
Это актуально как для mysql, так и для pg.

Апологеты mysql, так и pgsql — сделайте, пожалуйста.
Как читать explain — и куда смотреть на внутренние параметры БД.

Спасибо!
По PostgreSQL к примеру phpclub.ru/detail/store/pdf/postgresql-performance.pdf
По MySQL еще проще. Используйте перконовский визард tools.percona.com/wizard
Он требует регистрации но сразу все настраивает как надо.

Насчет узких мест у MySQL есть slow-query
У PostgreSQL есть онлайновая статистика, ее рекомендуется включать и использовать. У MySQL есть, но не настолько удобная и информативная.

Дополнительно учитывайте если у вас нет сложных запросов, то на указанных объемах памяти можно использовать MySQL будет работать немного быстрее. Это кстати и обуславливает частый выбор MySQL как базы данных для веб сервисов.
Пореквестировать можно всё. И я не против написать статьи на эти темы в части MySQL, но когда позволит свободное время.
Особенности логической репликации

А теперь расскажите какие из них реально доступны в MySQL. К примеру для первого сразу говорю придется не хило попрыгать с бубном. Плюс это может порождать больше проблем, чем давать профита. Насчет доступности для чтения у того же PostgreSQL вы лукавите. Там четко говорится slave открыт только на readonly. За каким вы указываете что там нельзя использовать уровни изоляции используемые при записи? С моей точки зрения это аргумент высосанный из пальца.

Есть некоторые особенности с failover, которые пользователю MySQL могут показаться странными, например невозможность возврата к старому мастеру после failover без его пересоздания.

Учитывая, что это делается банальной штатной софтиной, в отличии от MySQL это не такая уж проблема. К тому же никто не запрещает нагонять master через WAL файлы со slave. Да внезапно так можно делать.

Ну и да рассказывать что Олег Царёв поверхностно проходит по MySQL и PostgreSQL это сильно, может разберете аргументы приведенные им? Я вот разбора не вижу. Ну и подробнее про как CPU bound у вас переходит в IO bound. У вас перед переходом в IO bound сначала надо будет что-то с CPU bound сделать. А я имея каждый день с MySQL могу сказать что это та еще головная боль. И да если master у MySQL перегружен запросами, то slave берет и отстает, вплоть до его отвала, так-как ой мы потеряли запрос.

Ух, сколько сразу и вопросов и обвинений. Лень цитировать, отвечаю по порядку. Доступны все. Про бубны я и сам могу рассказать, только без бубнов нигде не бывает. Я всё объяснил, за каким я указываю уровни изоляции при записи — я вообще просто процитировал перевод официальной документации к PostgreSQL, так что вопрос не ко мне. Штатная софтина не отменаяет того факта, что мастер нужно пересоздавать. На это могут уйти часы, и от того, что это «штатная софтина», вам будет не легче.

И да, доклад Олега поверхностный, я довольно подробно разобрал главные пункты. Какое конкретно слово там непонятно? А придираться по мелочам у меня нет желания, хотя их там почти на каждом слайде. Как CPU bound переходит в IO bound я тоже объяснил — что именно там непонятно?
Ух, сколько сразу и вопросов и обвинений.

А то! И да мне просто сильно интересно сколько кода вы написали для СУБД :)

Доступны все. Про бубны я и сам могу рассказать, только без бубнов нигде не бывает.

Тогда ждем от вас статей где рассказывается как сделать каждую из них. А то я тоже могу сказать да все там доступно :)

Я всё объяснил, за каким я указываю уровни изоляции при записи

Правда? А я вот не увидел. К примеру для чего требуется использовать на SLAVE SELECT… FOR SHARE | UPDATE и такой чтобы он не был сферическим в вакууме.

Штатная софтина не отменаяет того факта, что мастер нужно пересоздавать. На это могут уйти часы, и от того, что это «штатная софтина», вам будет не легче.

Угу и про догонку WAL с текущего Master вы конечно же пропустили. Это вполне допустимый вариант и он вполне себе работает.

И да, доклад Олега поверхностный, я довольно подробно разобрал главные пункты. Какое конкретно слово там непонятно?

Да вот не разобрали. Фактически рассказали тоже самое, но только смотрите дети это фича :) Давайте уже как-то прорабатывать эту тему глубже все же.

Как CPU bound переходит в IO bound я тоже объяснил — что именно там непонятно?

Как избавились от CPU bound. Фишка в том что MySQL может жрать процессор как не в себя. В том числе и при логической репликации.

В MySQL постоянные проблемы в случае когда реплицируются не все базы — MySQL бай дизайн не способен корректно определить что нужно реплицировать, а что нет. Как с этим в Постгрес?
Это вы о statement-based репликации или о чём?
Так ведь написано же, что «With statement-based replication, the default database is checked for a match. With row-based replication, the database where data is to be changed is the database that is checked.»

Та же информация продублирована в dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html#option_mysqld_binlog-do-db:

«Row-based logging. Logging is restricted to database db_name. Only changes to tables belonging to db_name are logged; the default database has no effect on this.»
Наверное, спутал row-based с mixed. Или в 5.1 (с которой больше всего мучался) немного другое поведение было.
В PostgreSQL же WAL. Проще говоря все или ничего. Если нужно одну базу, то начинаем брать другие решения, которые работают уже на логическом уровне.
В 9.4 вроде-бы добавили

Однаку у меня в продуктиве, самая «большая версия» 9.3 с хвостиком. Так, что даже сказать об этом нечего.

Конкретно мы с админами убили кучу времени на очень простой сценарий (по которому собирались мигрировать на 5.7) — берём мастер пишем бинлоги, потому запускаем догон слейва и проверяем, как быстро он догоняется.
Мои графики в презентации — это как раз время догона.
Слайды 76 и 77: www.slideshare.net/tsarevoleg/ss-40969331?related=1
описывают железо и там есть ссылка на github со скриптами и конфигами/

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

Другой интересный тест — это догон слейва 5.7 с мастера 5.5 — он нужен для миграции без даунтайма — там всё тоже было очень печально, регрессия 40% по сравнению с 5.5
Впрочем, это было на 5.7 годичной давности, и я уже не работаю в компании mail.ru, где снова актуально перепроверить результаты на новой версии
Олег, рассказываю, что нужно было сделать в идеале. Нужно было написать хороший пост, на английском. Изложить связно проблему, выложить все метрики, в общем см. пост от Booking.com в качестве примера.

Потом можно было написать в internals@lists.mysql.com — там отвечают на внятно заданные вопросы и показать ссылку на пост. Дополнительно можно было связаться с людьми из Oracle, отвечающими за community. Их контакты легко найти и обратить их внимание на этот пост. Они бы связали с нужными людьми внутри.

Но это всё если разбираться самим совсем лень/нет времени/не тем заняты и т.д.

А можно было попробовать что-нибудь попрофилировать, что-то поанализировать самим. И по результатам создать баг на bugs.mysql.com. И тоже в блог, и тоже community представителям Oracle. Вот люди из Booing.com наверняка так и сделали, и результат этой работы мы видим в финальном релизе 5.7.

Я знаю, что ты общался с кем-то внутри Oracle. Но, видя уровень детализации, я не удивлён, что это общение ни к чему не привело. Просто чтобы грамотно задать вопрос, нужно знать половину ответа. Но я понимаю, что от доклада «PostgreSQL завоюет мир» профита гораздо больше, чем от какой-то конструктивной работы.
У Оракла есть все мои скрипты, описание бенчмарков, результаты измерений. Другими словами, полная информация.
Почему я говорю про блог и списки рассылки: они, как бы это помягче, часто помогают придать некоторый импульс разработчикам. Потому что блоги и списки читает много людей, общественный резонанс, вот это всё. Ну да ладно, вот ты связался с разработчиками напрямую. И они тебе ответили «О, ну тут ничего не сделать, PostgreSQL завоюет мир», так что ли? Они наверное тебе ответили, что работают над этим. И судя по результатам, действительно неплохо поработали.
Просто отмечаю: в третий раз за эту дискуссию пропускаю личные выпады и гипотезы с негативной коннотацией.

Оракл подробно запросил у меня детали бенчмарков и их смысл (для какой реальной задачи они нужны). Меня поблагодарили, ушли чинить.
Потом мне кидали ссылку на один пост про 5.7, но там без даталей было — из личного общения выяснил, что там был прирост что-то порядка единиц процентов на 128 тредов.
Начиная с этого момента тему в дальнейшем не отслеживал.
> Начиная с этого момента тему в дальнейшем не отслеживал.
Ну вот, как выяснилось, и зря не отслеживал.
Кстати говоря, связался с разработчиками ты уже _после_ доклада. Это важно, и я об этом знаю точно.
> Ну вот, как выяснилось, и зря не отслеживал.
Я предприму последнюю попытку объяснить, в общем-то, очевидные вещи.
На момент детального исследования параллельного slave я работал разработчиков проекта Target. В моих должностных обязанностях не было «разработки MySQL». Были конкретные проблемы проекта (отстающий slave на 5.5) и просили решения этих проблем.
Мер принято было много, в целом они помогли.
ОДНИМ ИЗ пунктов было изучения 5.7 (на дворе был 2014 год и 5.7.3) — поможет ли он с нашими проблемами или нет.
Мы провели ряд исследований, после коммуникаций с Oracle исправляли бенчмарки и повторяли исследования.
Никаких удовлетворительных результатов мы так и не получили, и ближе к концу лета 2014 года прекратили исследования.
Задач много других, 5.7.3 показал себя несостоятельным, имеющиеся проблемы смогли купировать другими способами (и на целый год этого даже хватило), я переключился на другие задачи.
Изученное и измеренное я оформил в виде доклада, доклад по отзывам людей, оказался информативным — «теперь мы наконец-то поняли, что происходит с репликацией, откуда наши проблемы и как с ними справляться». Минимум три success story есть, не считая отзывов вида «понял про репликацию и журналы из вашего доклада больше, чем после семестрового курса в ВУЗе».
Значит, доклад полезен людям

Вам не кажется странным, Алексей, критиковать мои действия с учётом данного контекста? Нигде, подчёркиваю — НИГДЕ — ни формально, ни по факту, ни в ожиданиях руководства не было слов о разработке MySQL. Только исследование, желательно — побыстрей, если не взлетает и непонятно что делать дальше — то забить, и работать над проблемами ПРОЕКТА.
А не MySQL.

> Кстати говоря, связался с разработчиками ты уже _после_ доклада. Это важно, и я об этом знаю точно.
У Вас, Алексей, неверная информация.
Я общался с Дмитрием Лёневым как минимум дважды:
1. На MySQL Meetup (которых был сильно раньше highload)
2. В процессе подготовки доклада к highload — он критиковал мой план доклада и дал много ценных замечаний
Но Вы «точно знаете», а с этим спорить бесполезно — успел убедиться за длительный промежуток времени
После доклада я просто повторил описание своего бенчмарка и выдал скрипты. User story: «нагруженный проект хочет смигрировать с 5.5 на 5.7 без даунтайма» я неоднократно описывал раньше.

Да, особенно круто критиковать доклад годовалой давности с современным MySQL. Впрочем, я почему-то не удивлён — ни подходом к критике доклада, ни повторения доклада (пожалуй, из неупомянутого мной лишь multi-source replication), ни личным выпадам.

Я нигде не критикую ни Вас, Олег Игоревич, лично, ни Ваши действия. Я даю советы. Как можно было бы сделать доклад более информативным, но менее «евангелистским». И как можно было бы достичь лучшего взаимодействия с разработчиками. Как к этим советам относиться — Ваше сугубо личное дело. А если Вы и дальше будете рассказывать про «информативность» доклада, я начну перечислять все технические несуразности. И получится очень неловко.
Спасибо, советы я принял к сведению, и благодарен за них. Если когда-нибудь придётся снова работать с MySQL и критиковать его — учту.

> А если Вы и дальше будете рассказывать про «информативность» доклада, я начну перечислять все технические несуразности. И получится очень неловко.

Странно, вроде бы в самом начале я делаю оговорку: невозможно описать технически корректно и при этом наглядно, и описанное в докладе — лишь грубые схемы, которые позволяют ПРЕДСТАВИТЬ как всё работают, но на деле СЛОЖНЕЙ.
И оговорки в процессе доклада я тоже делаю.
Технических несуразиц там много, и я этого никогда не отрицал. Самое важное с моей точки зрения — оставить в голове слушателя картинку про журналы (что это такое и зачем нужно), какие они бывают, какие у них особенности.
Эта цель вполне достигнута, отзывы и обратная связь это потверждает.

За сим раскланиваюсь

P.S. спасибо за советы и критику, учту в будущем.
Всегда самого наилучшего, и успехов на новом месте!
> Я общался с Дмитрием Лёневым как минимум дважды:

Так ты что, результаты тестов только Дмитрию Ленёву послал? Ну вот честно: баг открыть всё-таки нужно было. Просто потому, что все эти частные внутренние переписки «а у моего знакомого вот такие тесты» легко теряются. Особенно если «контакт» даже не в той группе, которая этими вещами занимается.

Если ты не хотел светить тесты их всегда можно отправить скрытым комментом (или скрытым файлом). Или же весь баг сделать скрытым с самого начала (потом, правда, будет практически невозможно повлиять на исправление скрытого бага, не являясь платным клиентом Оракла. Хотя я видела случаи когда человек делал скрытый баг и в тот же день test case публиковал на stackoverflow).

Открывать баги очень важно потому, что их видит не только «контакт из Оракла», но и люди из команды replication (или про что баг), и из поддержки, и из Community. И каждый из этих людей может подумать, что «баг важный, его нужно исправлять» и задействовать доступные внутренние механизмы. А доступа к частному письму у кого-то из них может не быть.
До людей из команды Replication это проблема точно не доходила, по крайней до мая 2014 года, тем более по MTS.
Скрипты есть же. Прогоните на новой версии и проверьте как же там стало лучше или нет. Оформите отдельной статьей мы с удовольствием почитаем. Но вот что-то мне подсказывает, что особого прогресса там нет. К примеру прогресс PostgreSQL вижу и он весьма и весьма позитивный. А вот прогресса в MySQL я не вижу. Фичи если и добавляются, то настолько медленно, что отслеживай что не отслеживай толку нет.
Не против, если я встряну в ваш спор небольшим рассказом про OrientDB? :-)

В терминах SQL там используется row-based репликация, каждая таблица реплицируется независомо, можно настраивать на каких узлах будут реплики каких таблиц, поддерживается как синхронная, так и асинхронная репликации, как master-slave, так и master-master, есть шардинг и прозрачный map-reduce по шардам. И всё это из коробки.
Если-бы эти 3 статьи, ещё и свести в один список вида:
Миф [.....]
(Опровержение|Подтверждение|Workaround) [
(ссылка на (документацию|блог разработчика|результаты тестирования))+
];

Было-бы очень удобно.
Собственно я бы еще добавил, что один из ведущих техлидов команды MySQL Replication Luís Soares в своем блогепостит описание новых фич (ну по ним можно примерно понять направление движения девелопмента), можно попробовать пообщаться с ним на темы физ. репликации и различных проблем.
Спасибо за статьи, было очень интересно ознакомиться.
Sign up to leave a comment.

Articles

Change theme settings