Project

General

Profile

Репликация MySQL

MySQL имеет встроенную репликацию, которая может послужить основой для нагруженных распределенных приложений.

Основная проблема, решаемая при репликации – синхронизация данных между серверами. Возможны различные топологии: один мастер (master) – много слэйвов (slave), много мастеров и т.д. Реплицировать можно весь сервер целиком, одну базу, одну таблицу. MySQL поддерживает на данный момент один тип репликаций: логическую репликацию (statement) . Построчная репликация (row-based) появится начиная с версии 5.1. Обе репликации имеют асинхронный характер, т.е. нет никаких гарантий, что процесс может длиться строго фиксированный промежуток времени. Репликация не работает вниз, т.е. база версии 5.0 не может быть реплицирована на версию 4.0. Основным условием репликации является включение бинарного логирования на мастере.

Что достигается с помощью репликации?

  • Распределение данных: данные можно копировать по разным дата-центрам.
  • Распределение нагрузки: запросы можно разносить между разными серверами с помощью простого базового round-robin DNS или используя Linux Virtual Server (LVS).
  • Бэкапы: репликация упрощает архивацию.
  • Устойчивость: наличие слэйвов позволяет уменьшить риск отказов системы.

Как работает репликация MySQL

Процесс репликации состоит из трех основных фаз:

  • происходит добавление записи в бинарный лог на мастере;
  • добавленные записи копируются из лога мастера слэйв-сервером в свой лог;
  • слэйв реплицирует свой лог в свою базу данных.

Во время этого процесса на мастере и на слэйве два отдельных треда устанавливают между собой коннект и передают репликационные данные.

Как конфигурировать master/slave

Для настройки репликации необходимо:

  • на каждом сервере настроить репликационный аккаунт;
  • сконфигурировать мастер и слэйв;
  • настроить на слэйве коннект и репликацию.

На мастере и на слэйве нужно выполнить команду:

mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
    -> TO repl@'192.168.0.%' IDENTIFIED BY 'p4ssword';

На мастере нужно сделать изменения в конфиге my.cnf:

  log_bin   = mysql-bin
  server_id = 10

Перезапускаем мастера и выполняем команду SHOW MASTER STATUS:

mysql> SHOW MASTER STATUS;
+------------------+----------+
| File             | Position |
+------------------+----------+
| mysql-bin.000001 |       98 |
...

На слэйве делаем аналогичные настройки в конфиге:

log_bin           = mysql-bin
server_id         = 2
relay_log         = mysql-relay-bin
log_slave_updates = 1
read_only         = 1

Здесь relay_log – промежуточный репликационный лог. log_slave_updates включает обмен данными между промежуточным и основным логами.

Запуск slave

Для запуска процесса репликации на слэйве нужно запустить команду:

mysql> CHANGE MASTER TO MASTER_HOST='server1',
    -> MASTER_USER='repl',
    -> MASTER_PASSWORD='p4ssword',
    -> MASTER_LOG_FILE='mysql-bin.000001',
    -> MASTER_LOG_POS=0;

После этого нужно сделать проверку:

mysql> SHOW SLAVE STATUS\G
********************* 1. row *******************
       Slave_IO_State:
          Master_Host: server1
          Master_User: repl
          Master_Port: 3306
        Connect_Retry: 60
      Master_Log_File: mysql-bin.000001
  Read_Master_Log_Pos: 4
       Relay_Log_File: mysql-relay-bin.000001
        Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001

Теперь запускаем репликацию:

mysql> START SLAVE;

Проверка:

mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
             Slave_IO_State: Waiting for master to send event
                Master_Host: server1
                Master_User: repl
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: mysql-bin.000001
        Read_Master_Log_Pos: 164
             Relay_Log_File: mysql-relay-bin.000001
              Relay_Log_Pos: 164
      Relay_Master_Log_File: mysql-bin.000001
      Slave_IO_Running: Yes
      Slave_SQL_Running: Yes

Запущен реплицирующий тред, который ждет сообщений от мастера. Если на мастере произойдут изменения, мы это увидим, запустив повторно команду SHOW SLAVE STATUS.

На мастере и на слэйве можно запустить команду, которая покажет информацию о тредах:

mysql> SHOW PROCESSLIST\G

Для мастера рекомендуется в конфиге поставить параметр:

  sync_binlog=1

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

В качестве основного движка базы данных рекомендуется InnoDB. Что касается MyISAM, то он может вести себя некорректно при остановках на слэйве. Для InnoDB рекомендуются следующие конфигурационные настройки мастера:

innodb_flush_logs_at_trx_commit=1 # синхронизация всех коммитов на диск
innodb_support_xa=1               # начиная с версии MySQL 5.0
innodb_safe_binlog                # только для версии MySQL 4.1

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

skip_slave_start
read_only

Различия в репликации

MySQL, включая версию 5.0, поддерживает только логическую (statement-based) репликацию. Когда слэйв реплицирует данные, фактически он выполняет тот же самый SQL-запрос, который выполнял мастер. У этого метода есть свои преимущества – он прост в реализации, размер лога при этом компактен. Но есть и недостатки: время выполнения запросов на мастере и на слэйве может сильно различаться. Некоторые выражения не реплицируются корректно, например функция CURRENT_USER(). Есть также проблемы с триггерами и хранимыми процедурами.

В версии 5.1 появится поддержка построчной (row-based) репликации. Преимущество этого варианта в том, что каждое выражение может быть реплицировано корректно и эффективно. При этом может возрасти размер лога, который уже нельзя будет инспектировать с помощью утилиты mysqlbinlog.

Почему построчная репликация эффективней? Возьмем пример для инсерта, который выбирает суммарный итог из очень большой таблицы:

mysql> INSERT INTO global_table(col1, col2, sum_col3)
    -> SELECT col1, col2, sum(col3)
    -> FROM my_table
    -> GROUP BY col1, col2;

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

Зато, с другой стороны, если взять выражение:

  mysql> UPDATE enormous_table SET col1 = 0;

то в этом случае для очень большой таблицы построчная репликация приведет к очень большому росту лога и будет неэффективной.

В версии 5.1 будет динамическое переключение между логической и построчной репликациями. По умолчанию будет применяться логическая репликация, это можно настраивать с помощью параметра binlog_format.

Топологии репликации

В MySQL для репликации есть несколько правил, независимо от их топологии: мастер может иметь несколько слэйвов; у каждого слэйва может быть только один мастер, т.е. multimaster не поддерживается.

Существует несколько топологических вариантов.

  • Мастер и несколько слэйвов.
  • Мастер-мастер в режиме active-active.
  • Мастер-мастер в режиме active-passive.
  • Мастер-мастер и несколько слэйвов.
  • Кольцо.
  • Дерево или пирамида.

Мастер и несколько слэйвов: этот вариант мы уже рассмотрели детально.
Вместо одного слэйва здесь их будет несколько, при этом они не будут общаться друг с другом.
Эта схема хороша в том случае, когда писать будет мастер, а основная нагрузка на чтение будет приходиться на слэйвы.
В этой схеме слэйвы можно наращивать постепенно.

Тут можно реализовать следующие идеи:

  • каждый слэйв исполняет свою роль – например, выборочное индексирование;
  • использовать слэйв для аварийного восстановления;
  • использовать слэйв для бэкапа или разработки.

Мастер-мастер в режиме active-active: этот вариант известен как двунаправленная репликация. Каждый из двух серверов выступает одновременно в качестве мастера и в качестве слэйва. В этом варианте есть проблема с разрешением конфликтов, когда, например, два запроса начинают одновременно менять одну и ту же строку или когда происходит одновременная автоинкрементная вставка в таблицу на оба сервера. В версии 5.0 появились специальные параметры конфига: auto_increment_increment, auto_increment_offset, которые генерируют неконфликтные инсерты. Вообще говоря, в этой схеме можно придумать логику апдейтов, которая разрушает синхронизацию между серверами или создает между ними конфликты.

Мастер-мастер и несколько слэйвов: здесь можно назначить один или более слэйвов на каждый мастер. Эта схема уменьшает трафик между мастером и слэйвом.

Кольцо – это вторая схема, в которой участвуют три и более мастера. Если в этой схеме одна нода выйдет из строя, это приведет к зависанию репликации.
Это хрупкая схема, и ее лучше избегать.

Древовидная структура может иметь место для очень большого числа слэйвов. На вершине находится мастер, а каждый последующий слэйв может быть родителем для других слэйвов.
Управлять такой структурой сложнее в силу ее природы – все зависит от уровня слэйва, который может остановиться, и от числа его зависимостей.

Also available in: PDF HTML TXT