Репликация Master-Slave в MySQL

Репликация позволяет решать несколько очень важных задач — это повышение доступности и надёжности хранения данных. Начиная с версии 4.1.13 MySQL поддерживает кластеризацию. Итак, что даёт нам репликация?

  1. Резервное копирование в режиме online.
  2. Высокая надёжность хранения данных. Если один сервер по каким либо причинам повредился и данные потерялись, то у нас всегда будет зекрало базы.
  3. Высокая доступность системы. В случае, если один сервер перестал работать, мы может переключить наших клиентов на другой сервер, туда, куда призводилась репликация.
  4. Масштабирумость системы. Это отдельный разговор, его мы как нибудь затронем, но с помощью разных видов репликаций можно достигать почти горизонтальной масштабируемости, когда при N увеличении компьютеров в вашем кластере, скорость работы вашего сервиса увеличивается “почти” в N раз. Я говорю почти, потому что кроме самой базы данных, ещё много других “бутылочных горлышек” и связывающий канал между вашими серверами — тоже отдельная песня.

Терминология

Репликация — процесс копирования данных одной БД между другими БД.

Master Server — Главный сервер, с которого производиться копирование.

Slave Server — Подчинённый сервер, на который, производиться копирование данных.

Что нам нужно

Один master сервер и один slave-сервер. Все изменения на master-сервере будут синхронизироваться на slave сервер.

Как это работает

Slave-сервер с определённой периодичностью будет опрашивать master-сервер на предмет изменений в базе. Таким образом все изменения в master-сервере будут повторяться на slave-сервере. Таким образом создаётся избыточность данных на двух серверах и тем самым достигается высокая доступность и надёжность данных. Важным преимуществом между “холодным копированием” заключается в том, что мы переносим по сети только изменения, а не все данные каждый раз. Тем более не стоит забывать что во время создания backup`а мы нагружаем наш master-сервер. Здесь же всё иначе, master-сервер все изменения в базе пишет в “бинарный журнальный лог”, присваивая каждой операции номер. Когда slave-сервер обращается к нашему главному серверу, то он сообщает номер последней операции, которую он уже произвёл у себя и получает все новые изменения отсчитывая от этого номера.

Настраиваем

Первым делом надо включить “Бинарный журнал” на master-сервере. Это файл, в котором регистрируются все изменения данных. Однако, опреаторы update и delete, которые не затронули ни одной строки — регистрироваться в журнале не будут. Включение журнала немного понижают общую производительноть базы, но не сильно, примерно на 1%. Зато, в случае падения базы, этот журнал используется для “автоматического восстановления после сбоя”. Для включения этого журнала отредактируем конфигурационный файл (у меня в Gentoo Linux это /etc/mysql/my.cnf)

log-bin = my-bin

my-bin в данном случае — это имя файла бинарного лога. В ходе работы базы в папке с данными (у меня это /var/lib/mysql) будут создаваться файлы my-bin.000001, my-bin.000002 и так далее, при каждом старте базы, будет создан новый файл. Вместе с этим будет создан файл my-bin.index в котором будут перечислен список всех бинарных логов. Продолжим настройку нашего главного сервера, добавим следующие строки:

server-id = 1
slave-compressed = 1
binlog-do-db = mydb

server-id является обязательным параметром, это идентификатор базы, пускай будет 1, каждый сервер в схеме репликаций должен иметь уникальный номер. На slave-сервере мы укажем server-id=2. slave-compressed я включил, потому что мой slave-сервер находиться не “рядом” и передача идёт по сети, в этом случае можно повысить скорость и разрешить сжимать поток. bin-do-db — необязательный параметр, позволяет указать изменения какой именно базы будет писаться в бинарный журнальный лог.

Создадим отдельную учётную запись на головном сервере c привилегиями REPLICATION SLAVE, SELECT, RELOAD, SUPER. При создании учётной записи не забудьте правильно указать “Хост”. Например, если все наши slave-сервера находятся в зоне webnext.ru то мы можем ограничить доступ как ‘%.webnext.ru’.

Перед запуском подчинённого (slave) сервера, на нём необходимо разместить полную копию данных главного (master) сервера. Задача состоит в том, что на головном сервере необходимо сделать дамп базы в режиме блокировки на запись. И пока делается дамп необходимо узнать номер журнала и смещение от начала файла. Для этого выполните запрос:

SHOW master STATUS;

В столбце File указано имя текущего журнального файла, а в столбце Position — смещение относительно начала файла. Эти значения представляют собой координаты, с которых подчинённому серверу следует получать новые изменения.

Далее на slave-сервере следует выполнить следующую sql-команду.

CHANGE master TO
  master_host = 'master_host',
  master_user = 'user'.
  master_password = 'password',
  master_log_file = 'log_file',
  master_log_pos = log_pos;

Тут master_host — хост или ip главного (master) сервера с которого мы делаем репликацию. user и password — имя пользователя, которого мы завели специально для репликаций и его пароль. log_file и log_pos — имя текущего журнального файла на главном сервере и смещение от начала файла, эти поля мы получили выше с главного (master) сервера. И последнее что осталось, это запустить на подчинёном сервере процесс репликации, это делается sql-командой.

start slave;

Регистрация доменов RU за 350р!!!
Совместно с регистратором onreg.ru мы проводим акцию! Купи домен для своего блога или нового интернет проекта по выгодным ценам. Так домен в зоне RU стоит всего 350 рублей. При покупке нескольких доменов, возможны скидки. На onreg.ru есть система тикетов, через которую мы всегда готовы ответить на все ваши вопросы и предложения.


Спальные детские кроватки. Детские кроватки от Olmitos.
Комментарии
  • Jason — 26.12.2007 #1
    Можно ли на slave сервере реплицировать одну две конкретных базы данных, а остальные чтоб работали в стандартном режиме? Или придется ставить два сервера на разных портах?
  • Jason — 26.12.2007 #2
    Все вроде нашел нужный параметр ща буду пробоввать B)
    replicate-do-db=database_name
  • php_prog — 01.03.2008 #3
    А это всё надо среднестатистическому web-мастеру или это только для каких-нить масштабных проектов?
  • blacknot — 01.03.2008 #4
    1. Распределение нагрузки, если нагрузка большая то операции чтения можно разделить между n slave-серверов
    2. Сохранность данных. Если на сервер упадёт метиорит :) то вы потеряете все данные, а холодное копирование -- не совсем удачное решение, репликации же позволят вам получать только инкрементальные данные, тоесть только изменения
  • Алмаз Асанкожоев — 12.03.2008 #5
    Очень интересный пост. Все хорошо расписано, но у меня появилось несколько вопросов:

    1. А если на мастер сервер сделать DELETE FROM TABLE; то и со всех slave серверов удалятся данные? Если да, то каким образом можно избежать этого?
    2. Каким образом можно разделить операции чтения между n slave-серверами?
    3. Насколько я понял INSERT, DELETE, ALTER и т.п. можно делать только на мастер сервере. Тогда вопрос: что делать если метеорит грохнулся именно на мастер? Есть ли схемы репликации master-master?

    P.S.: очень понравился дизайн блога. Сам рисовал?
  • blacknot — 22.03.2008 #6
    1. Совершенно верно, в теории надёжности систем рассматриваются варианты обхода разных случаев. Например вы можете иметь активные слейвы, с которых постоянно берутся данные и пассивный слейв, который высасывает изменения раз в несколько часов или даже раз в сутки, и в случае, если что-то пошло не так и, кто-то, как-то, всё удалил, то у вас будет всегда копия того, что было "утром". Кроме того всё что реплицируеться, делается это из журнального лога, в него mysql кидает все операции, которые он делал. Он бинарный, но его можно конвертировать в текстовые файлы. и вытащить данные, однажды я удалил одну статью и вытащил все их копии за весь день из этого журнала.
    2. Посмотрите интерфейс mysql для того же PHP и вы наткнётесь на абсолютно фантастическую штуку -- достаточно лишь указать список всех slave серверов и он будет читать из них, а писать в master.
    3. Да есть, http://code.google.com/p/mysql-master-master/, но как я понимаю, эти схемы требуют больших затрат на операции, ведь они трубуют полной синхронизации, а не отложенной, как в master-slave. Поэтому любая операция записи данных, будет ждать ответа, что эти данные были записаны и в второй мастер-сервер. Так что, лучше в случае метеорита, потерять данные за пару секунд, поскорбить убитый за сервер и перевести какой нибудь slave в master.

    P.S.: да :-)
  • test — 19.04.2008 #7

    sdfsdf
    fdgdg

  • robot — 29.04.2008 #8

    I’m not robot! He-he-he!!!

  • Любовь — 01.07.2008 #9

    I’m not robot! Vauuuu

  • Алексей Смирнов — 08.08.2008 #10

    Здравствуйте!
    Всё настроил по статье, проверил. Все работает!!!

    Подскажите, пожалуйста, ещё про такую ситуацию:

    Остановил SLAVE-сервер, произвёл изменения данных в MASTER-сервере, запустил SLAVE-сервер, но у него обновления не проявились. Что делать???

  • Андрей Клаус — 29.08.2008 #11

    2 blacknot — 22.03.2008:

    blacknot, скажи глупому, как.. КАК указать в php список слейвов? Уже весь php.net вроде пересмотрел, не могу найти того что нужно… буду очень благодарен за маленький пример использования функции. всего одну-две строчки кода, пжл.

  • master — 22.09.2008 #12

    Интересно, а реально ли в майскле сделать репликаци мастер-слэйв только на некоторые таблицы базы.
    Интересует именно такая задача.

  • master — 22.09.2008 #13

    О, нашёл сам уже.
    Кому надо:
    на слэйве добавляете
    replicate-do-table=dbname.tablename1
    replicate-do-table=dbname.tablename2

    статья хорошая…информативная

  • aosiniao — 24.10.2008 #14

    О, блин, привет, Костя! Искал мануал по репликации гуглом, и нашёл твой сайт! Малацца! :)

  • Anton — 08.01.2009 #15

    подскажите, с какой частотой слейв будет обращаться на мастер?
    то есть если я добавил запись на мастере, через какое время она появится на слейве?

  • blacknot — 18.01.2009 #16

    У меня почти сразу, не успеваю глянуть - уже есть

  • Кирилл — 30.07.2009 #17

    Cпасибо, полезная статья!

  • Евгений — 10.01.2010 #18

    везде ищу, и не могу найти ответа на вопрос:

    как восстановить репликацию после перезагрузки slave? я уже пробовал, слэйв получал только настоящие изменение, а не те, которые были сделаны, до перезагрузки

    так как быть?

  • Vii — 10.02.2010 #19
    Евгений

    В my.cnf добавь

    server-id=2

    master-host=IPhost

    master-user=user

    master-password=passwort

    replicate-do-db=db1

    replicate-do-db=db2

    log-bin=bin-log

  • playnet — 24.04.2010 #20
    В my.cnf добавь

    Бессмысленно. Мускуль читает эти строки только 1 раз, потом создает свой файлик с этими реквизитами и в конфиге уже не роляет.

  • Murz — 21.07.2010 #21

    А есть ли какой скрипт или софтина чтобы синхронизировать текущую базу с той что есть в бекапе? Т.е. посмотреть какие таблички изменились и обновить только их.

    А то я смотрю бинарные логи под гигабайт набегают в сутки, а реальных изменений по факту в базе получается мало и смысла гонять между серверами гигабайты каждый день нету.

    Хотелось бы просто аплоадить на бекап-сервер только те таблички, которые изменились.

    По-идее можно делать просто rsync файлов /var/lib/mysql, но может попасться момент когда данные в файл не полностью записались и в результате файл в бекапе получится кривой.

    Т.е. нужно бы делать rsync каждого файла, но на этот момент сказать mysql-базе чтобы записала все изменения в него, а пока файл синхронизируется новые изменения туда не писала.

    Каким-нибудь образом можно организовать такую синхронизацию?

Оставить комментарий
Ваше имя:
E-mail:
Сайт (блог):
Сообщение:
Если вы не робот, введите код: