Що таке реплікація у MySQL? Налаштування реплікації Master-Slave у MySQL Що таке mariadb galera

Реплікація – механізм синхронізації вмісту кількох копій об'єкта. Під цим процесом розуміється копіювання даних із одного джерела на безліч інших і навпаки.

Позначення:

  • master – головний сервер, дані якого необхідно дублювати;
  • replica - полагоджений сервер, що зберігає копію даних головного

Для налаштування реплікації MySQL необхідно виконати нижче описану послідовність дій, але це не догма і параметри можуть змінюватися в залежності від обставин.

На головному сервері відредагуємо файл файл my.cnf, до секції mysqld додати рядки:

Server-id = log-bin = mysql-bin log-bin-index = mysql-bin.index log-error = mysql-bin.err relay-log = relay-bin relay-log-info-file = relay-bin. info relay-log-index = relay-bin.index expire_logs_days=7 binlog-do-db =

  • - Унікальний ідентифікатор сервера MySQL, число в діапазоні 2 (0-31)
  • - ім'я бази, інформація про яку писатиметься в бінарний журнал, якщо баз кілька, то для кожного необхідний окремий рядок з параметром binlog_do_db

На підлеглом відредагуємо файл файл my.cnf, до секції mysqld додати рядки:

Server-id = master-host = master master-user = replication master-password = password master-port = 3306 relay-log = relay-bin relay-log-info-file = relay-log.info relay-log-index = relay-log.index replicate-do-db =

На головному сервері додамо користувача replication із правами на реплікацію даних:

GRAANT REPLICATION SLAVE ON *.* TO "replication"@"replica" IDENTIFIED BY "password"

Заблокуємо бази, що реплікуються, на головному сервері від зміни даних, програмно або за допомогою функціоналу MySQL:

Mysql@master> FLUSH TABLES WITH READ LOCK; mysql@master> SET GLOBAL read_only = ON;

Для розблокування використовується команда:

Mysql@master> SET GLOBAL read_only = OFF;

Зробимо резервні копії всіх баз даних на головному сервері (або тих, які нам необхідні):

Root@master# tar -czf mysqldir.tar.gz /var/lib/mysql/

або засобами утиліти mysqldump:

root@master# mysqldump -u root -p --lock-all-tables > dbdump.sql

Зупинимо обидва сервери (в окремих випадках можна обійтися і без цього):

root@master# mysqlamdin -u root -p shutdown root@replica# mysqlamdin -u root -p shutdown

Відновимо бази даних, що реплікуються, на підпорядкованому сервері за допомогою копіювання директорії. Перед початком реплікації бази даних мають бути однакові:

Root@replica# cd /var/lib/mysql root@replica# tar -xzf mysqldir.tar.gz

або функціоналу mysql, тоді mysql на підпорядкованому сервері не було необхідності зупиняти:

Root@replica# mysql -u root -p< dbdump.sql

Запустимо mysql на головному сервері (а потім - на підлеглому, якщо це необхідно):

Root@master# /etc/init.d/mysql start root@replica# /etc/init.d/mysql start

Перевіримо роботи головного та підлеглого серверів:

Mysql@replica> start slave; mysql@replica> SHOW SLAVE STATUS\G mysql@master> SHOW MASTER STATUS\G

На підлеглому сервері перевірити логи у файлі master.info, там мають бути запити на зміну даних у базі. Так цей бінарний файл необхідно спочатку перетворити його в текстовий формат:

Root@replica# mysqlbinlog master.info > master_info.sql

При виникненні помилок можна використовувати команди:

Mysql@replica> stop slave; mysql@replica> RESET SLAVE; mysql@master> RESET MASTER;

і повторити всі дії, починаючи з блокування баз даних.

Для гарячого додавання серверів реплікації можна використовувати синтаксис:

Mysql@replica> SHOW SLAVE STATUS\G mysql@master> SHOW MASTER STATUS\G mysql@replica-2> CHANGE MASTER TO MASTER_HOST = "master", MASTER_USER = "replication", MASTER_PASSWORD = "password", MASTER_LOG_FILE bin.000004", MASTER_LOG_POS = 155; mysql@replica-2> START SLAVE;

Інформація зі статусів покаже позицію та ім'я поточного логового файлу.

У разі асинхронної реплікації оновлення однієї репліки поширюється на інші через деякий час, а не в тій самій транзакції. Таким чином, при асинхронній реплікації вводиться затримка або час очікування, протягом якого окремі репліки можуть бути фактично неідентичними. Але в даного виду реплікації є й позитивні моменти: головному серверу не треба турбуватися про синхронізацію даних, можна блокувати базу (наприклад, для створення резервної копії) на підлеглій машині без проблем для користувачів.

Список використаних джерел

  1. Habrahabr.ru - Основи реплікації в MySQL (http://habrahabr.ru/blogs/mysql/56702/)
  2. Вікіпедія (http://ua.wikipedia.org/wiki/Реплікація_(обчислювальна_техніка))

При повному або частковому використанні будь-яких матеріалів із сайту ви зобов'язані явно вказувати посилання на як джерело.

Всім доброго дня! Сьогодні в нашій статті ми розглянемо приклади настроювання реплікації типу “master-slave”.

Трохи теорії

Навіщо потрібна реплікація? Насамперед це підстраховка на випадок, якщо основний mysql-сервер вийде з ладу, тоді можна переключитися на slave-сервер і продовжити роботу. По друге, це можливість зменшити навантаження на основний сервер Mysql, використовуючи master-сервер тільки для запису, а операції на читання виконувати на slave-сервері. Як відбувається реплікація? Master-сервер пише binlog-і, в яких вказує операції, що виконуються над базою даних (базами даних) та запам'ятовує зміщення в журналі від його початку до поточного запису (позицію). Slave-сервер підключається до master-у, порівнює значення позицій та зчитує зміни в журналі починаючи зі значення власної позиції та закінчуючи значенням позиції master-a. Зміни (команди) він застосовує до баз даних на slave-сервері.

Встановлення та налаштування Master

Змінюємо my.cnf на головному сервері:

Server-id = 1 - вказуємо id сервера log_bin = /var/log/mysql/mysql-bin.log - найменування лога та його шлях

Невелике уточнення: за замовчуванням майстер пише binlog-і для всіх баз даних, це можна змінити за допомогою "binlog-do-db". У логи записуватиметься значення, коли використовуватиметься певна БД, зміни в інших БД не записуватимуться.Тут можна вказати, скільки днів зберігати логи, який їх максимальний розмір (параметри expire_logs_days і max_binlog_size). Додаємо в MySQL користувача, під правами якого проводитиметься реплікація:

GRANT replication slave ON *.* TO имя_пользователя@ip_slave_сервера IDENTIFIED BY "пароль";

replication slave - привілей, що дозволяє користувачеві читати binlog-і. ip_slave_сервера - ip сервера, з якого підключатиметься користувач. Перезавантажуємо mysql-сервер:

/etc/init.d/mysql restart

Перевіряємо роботу майстра:

Show master status;

Повинні побачити назву binlog-a та позицію в ньому. При виконанні команд над БД позиція змінюватиметься.

Налаштування Slave

У файл my.cnf вносимо зміни:

Server-id = 2 – ідентифікатор slave-сервера повинен обов'язково відрізнятися від ідентифікатора master. relay-log = /var/lib/mysql/mysql-relay-bin - як і двійковий журнал, складається з набору пронумерованих файлів, що містять події, які описують зміни у базі даних. relay-log-index = /var/lib/mysql/mysql-relay-bin.index - індексний файл, який містить імена всіх файлів журналів relay, що використовуються. replicate-do-db = БД, яка реплікуватиметься.

Важливе зауваження! При організації cross db (коли використовується одна база даних, а дані оновлюються в іншій базі даних) в налаштуваннях майстер-сервера не потрібно вказувати binlog-do-db, binlog-і повинні писатися для всіх баз даних, а в налаштуваннях slave потрібно замість replicate-do -db вказати replicate-wild-do-table=db_name.%, де db_name - ім'я БД, що реплікується.Перезавантажуємо mysql-сервер:

/etc/init.d/mysql restart

Увімкнення реплікації

SET GLOBAL read_only = ON;

Дивимося стан master-a:

Show master status;

Запам'ятовуємо значення File та Position (а краще їх записати). Наразі значення Position не повинно змінюватись. Робимо дамп майстра командою mysqldump:

Mysqldump -uname -ppassword db_master_name > dump_db,

де name – ім'я користувача, password – пароль, db_master_name – ім'я БД, dump_db – назва дампа. Після завершення дампа дозволяємо запис у БД:

SET GLOBAL read_only = OFF;

Переносимо дамп на slave та розвертаємо

Mysql -uname -ppassword db_slave_name< dump_db

Налаштовуємо реплікацію

CHANGE MASTER TO MASTER_HOST = "ip-майстра", MASTER_USER = "ім'я_користувача", MASTER_PASSWORD = "password", MASTER_LOG_FILE = "назва лога", MASTER_LOG_POS = позицію;

ip-майстра - ip сервера, у якому розташований master, имя_пользователя - ім'я користувача, якого ми створили на master-е, назва лога - значення File на майстрі, коли робив дамп БД, позицію - значення Position на майстрі, коли робив дамп БД. Запускаємо slave:

Start slave;

Дивимося як іде реплікація: На майстрі: SHOW MASTER STATUS\G На slave: SHOW SLAVE STATUS\G

Налаштування безпеки на master-сервері

Параметр bind-address в /etc/mysql/my.cnf задає, яку ip-адресу mysql-сервер слухатиме в очікуванні з'єднання. Зазвичай вона має значення bind-address = 127.0.0.1. Але після налаштування slave-сервера нам потрібно дозволити підключення зі slave-сервера і при цьому повинні працювати локальні підключення. Bind-address може дозволити підключення тільки з одного IP або з усіх. Т.к. нам потрібно вказати більше одного IP для з'єднання, ми коментуємо рядок з bind-address = 127.0.0.1. Тепер mysql-сервер прийматиме з'єднання з усіх ip-адрес, що дуже небезпечно. Вирішити цю проблему нам допоможе iptables:

Iptables -I INPUT -p tcp -s ip_slave_server-a --dport 3306 -j ACCEPT -на початку дозволяємо підключення з ip-адреси slave-сервера iptables -I INPUT -p tcp --dport 3306 -j DROP - потім забороняємо підключення з решти ip-адрес.

Тепер у нас буде працювати 2 MySQL сервери в режимі master-slave, що суттєво підвищує надійність сайту та для деяких Drupal сайтів допомагає збільшити швидкість роботи. У наступній статті розглянемо перемикання між режимами master та slave у разі падіння master сервера.

Нещодавно мене попросили розповісти про реплікації у MySQL. Я вирішив, що ця тема може бути багатьом корисною, тому цій статті я розповім про те, що таке реплікація в MySQL, коли вона потрібна і як її налаштувати.

Головне завдання реплікації - об'єднувати потужності кількох серверів. Допустимо, у Вашого сайту виділений сервер, але згодом він стає дуже відвідуваним і вже не витримує навантаження. В результаті, починаються гальма та регулярні падіння сервера. Найпростіший спосіб - це купити потужніший сервер, і так більшість і надходить. Але рано чи пізно настає момент, коли вже вартість зростання ціни на сервер не відповідає зростанню його продуктивності, тому вигідніше купити 2 різних серверів за менші гроші.

У результаті Ваша база буде відразу на двох серверах. Коли один головний сервер (він же головний) вже не справляється, йде перемикання на запасний.

Усе запити поновлення бази завжди йдуть на головний сервер. Після оновлення головного сервера, він поміщає інформацію в окремий файл, звідки й беруть всю інформацію підлеглі сервера. А ось операції вибірки, яких зазвичай більшість, і вони найповільніші, вже можуть передаватися на підлеглі сервери, оскільки і там, і там дані однакові.

Тепер розберемо, як налаштовується реплікація у MySQL:

  1. Встановіть самі свіжі версії MySQLна всі сервери.
  2. Створіть на головному сервері користувача з привілеєм REPLACATION SLAVE. Як адресу, з якої він може підключатися, вкажіть " Усе".
  3. Зупиніть усі сервери.
  4. В налаштуваннях MySQL(у файлі my.cnf) в розділі додайте наступні рядки: log-bin
    server-id=1 Зверніть увагу, що server-idна всіх серверах має бути різний. Фактично це те, що відрізняє один сервер від іншого.
  5. На підлеглих серверах додайте в налаштування MySQLнаступні рядки: master-host=ім'я_головного_хоста
    master-user=логін_створеного_користувача
    master-password=пароль_створеного_користувача
    master-port=порт_для_підключення_до_головного_сервера
    server-id=id_даного_підпорядкованого_сервера
  6. Перенесіть усі базиз головного сервера на підлеглі.
  7. Запустітьголовний сервер, потім усі підлеглі.

З реплікацією серверів MySQL я познайомився нещодавно, і в міру проведення різних дослідів з налаштуванням, записував, що у мене виходило. Коли матеріалу набралося чимало, виникла ідея написати цю статтю. Я постарався зібрати поради та рішення з деяких основних питань, з якими я зіткнувся. По ходу справи я даватиму посилання на документацію та інші джерела. Не можу претендувати на повноту опису, але я сподіваюся, що стаття буде корисною.

Невелике введення

Реплікація (від латів. replico -повторюю) - це тиражування змін даних з головного сервера БД на одному або кількох залежних серверах. Головний сервер називатимемо майстром, а залежні - репліками.
Зміни даних, що відбуваються на майстрі, повторюються на репліках (але не навпаки). Тому запити на зміну даних (INSERT, UPDATE, DELETE тощо) виконуються лише на майстрі, а запити на читання даних (простіше кажучи, SELECT) можуть виконуватися як на репліках, так і на майстрі. Процес реплікації на одній з реплік не впливає на роботу інших реплік, і практично не впливає на роботу майстра.
Реплікація проводиться з допомогою бінарних логів , які ведуть майстра. У них зберігаються всі запити, що призводять (або потенційно призводять) до змін БД (запити зберігаються не в явному вигляді, тому якщо захочеться їх подивитися, доведеться скористатися утилітою mysqlbinlog). Бінлоги передаються на репліки (бінлог, завантажений з майстра, називається "relay binlog") і збережені запити виконуються, починаючи з певної позиції. Важливо розуміти, що з реплікації передаються не самі змінені дані, лише запити, викликають зміни.
При реплікації вміст БД дублюється на кількох серверах. Навіщо потрібно вдаватися до дублювання? Є кілька причин:
  • продуктивність та масштабованість. Один сервер може не справлятися з навантаженням, яке викликається одночасними операціями читання та запису в БД. Вигода від створення реплік буде тим більше, чим більше операцій читання посідає одну операцію запису у вашій системі.
  • відмовостійкість. У разі відмови репліки всі запити читання можна безпечно перекласти на майстра. Якщо майстер відмовиться, запити запису можна перекласти на репліку (після того, як майстер буде відновлено, він може взяти на себе роль репліки).
  • резервування даних. Репліку можна "гальмувати" на якийсь час, щоб виконати mysqldump, а майстер - ні.
  • відкладені обчислення. Тяжкі та повільні SQL-запити можна виконувати на окремій репліці, не боячись перешкодити нормальній роботі всієї системи.
Крім того, є деякі інші цікаві можливості. Оскільки на репліки передаються не самі дані, а запити, що їх зміни, ми можемо використовувати різну структуру таблиць на майстрі і репліках. Зокрема, може відрізнятися тип таблиці (engine) чи набір індексів. Наприклад, для здійснення повнотекстового пошуку ми можемо використовувати тип таблиці MyISAM на репліці, незважаючи на те, що майстер буде використовувати InnoDB.

Налаштування реплікації

Припустимо, у нас є база даних MySQL, що працює, вже наповнена даними і включена в роботу. І через одну з причин, описаних вище, ми збираємося включити реплікацію нашого сервера. Наші вихідні дані:
  • IP-адреса майстра 192.168.1.101, репліки - 192.168.1.102.
  • MySQL встановлений та налаштований
  • потрібно налаштувати реплікацію БД
  • ми можемо призупинити роботу майстра на деякий час
  • у нас, зрозуміло, є root на обох машинах
Налаштування майстра
Обов'язково вкажемо унікальний ID сервера, шлях для бінарних логів та ім'я БД для реплікації у секції:
server-id = 1
log-bin = /var/lib/mysql/mysql-bin
replicate-do-db = testdb
Переконайтеся, що ви маєте достатньо місця на диску для бінарних логів.

Додамо користувача replication, під правами якого буде реплікація. Буде достатньо привілею "replication slave":
mysql@master> GRANT replication slave ON "testdb". * TO "replication"@"192.168.1.102" IDENTIFIED BY "password";

Перезавантажимо MySQL, щоб зміни в конфізі набули чинності:
root@master# service mysqld restart

Якщо все пройшло успішно, команда show master status повинна показати приблизно таке:
mysql@master> SHOW MASTER STATUS\G
File: mysql-bin.000003
Position: 98
Binlog_Do_DB:
Binlog_Ignore_DB:
Значення position має збільшуватися у міру того, як вносяться зміни до БД на майстрі.

Налаштування репліки
Вкажемо ID сервера, ім'я БД для реплікації та шлях до relay-бінлогів у секції конфігу, потім перезавантажимо MySQL:
server-id = 2
relay-log = /var/lib/mysql/mysql-relay-bin
relay-log-index = /var/lib/mysql/mysql-relay-bin.index
replicate-do-db = testdb

Root@replica# service mysqld restart

Переносимо дані
Тут нам доведеться заблокувати БД для запису. Для цього можна або зупинити роботу додатків, або скористатися встановленням прапорця read_only на майстрі (увага: на користувачів із привілеєм SUPER цей прапор не діє). Якщо у нас є таблиці MyISAM, зробимо також "flush tables":
mysql@master> FLUSH TABLES WITH READ LOCK;
mysql@master> SET GLOBAL read_only = ON;

Подивимося стан майстра командою show master status і запам'ятаємо значення File і Position (після успішного блокування майстра вони не повинні зміняться):
File: mysql-bin.000003
Position: 98

Робимо дамп БД, і після завершення операції знімаємо блокування майстра:
mysql@master> SET GLOBAL read_only = OFF;

Переносимо дамп на репліку і відновлюємо дані.
Нарешті, запускаємо реплікацію командами "change master to" та "start slave" і подивимося, чи все пройшло добре:
mysql@replica> CHANGE MASTER TO MASTER_HOST = "192.168.1.101", MASTER_USER = "replication", MASTER_PASSWORD = "password", MASTER_LOG_FILE = "mysql-bin.000003", MASTER_LOG_POS =
mysql@replica> start slave;
Значення MASTER_LOG_FILE та MASTER_LOG_POS ми беремо з майстра.

Подивимося, як йде реплікація командою show slave status:
mysql@replica> SHOW SLAVE STATUS\G
Slave_IO_State: Помилка для майстра до одного місця
Master_Host: 192.168.1.101
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 98
Relay_Log_File: mysql-relay-bin.001152
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: testdb, testdb
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 5

Найцікавіші зараз значення я виділив. При успішному початку реплікації їх значення мають бути приблизно такими, як у лістингу (див. опис команди show slave status у документації). Значення Seconds_Behind_Master може бути будь-яким цілим числом.
Якщо реплікація йде нормально, репліка слідуватиме за майстром (номер лога в Master_Log_File і позиція Exec_Master_Log_Pos зростатимуть). Час відставання репліки від майстра (Seconds_Behind_Master), в ідеалі, має дорівнювати нулю. Якщо воно не скорочується або зростає, можливо, що навантаження на репліку надто високе - воно просто не встигає повторювати зміни, що відбуваються на майстрі.
Якщо значення Slave_IO_State порожнє, а Seconds_Behind_Master дорівнює NULL, реплікація не почалася. Дивіться лог MySQL для з'ясування причини, усувайте її та заново запускайте реплікацію:
mysql@replica> start slave;

Шляхом цих нехитрих дій ми отримуємо репліку, дані якої ідентичні даним на майстрі.
До речі, час блокування майстра – це час створення дампи. Якщо він створюється неприпустимо довго, можна спробувати вчинити так:

  • заблокувати запис у майстер прапором read_only, запам'ятати позицію та зупинити MySQL.
  • після цього скопіювати файли БД на репліку та увімкнути майстер.
  • почати реплікацію звичайним способом.
Існує кілька способів створити репліку без зупинки майстра взагалі, але вони спрацьовують не завжди.

Додаємо репліки

Нехай у нас вже є працюючі майстер та репліка, і нам потрібно додати до них ще одну. Зробити це навіть простіше, ніж додати першу репліку до майстра. І набагато приємніше те, що немає необхідності зупиняти для цього майстер.
Для початку налаштуємо MySQL на другій репліці і переконаємося, що ми внесли потрібні параметри до конфіг:
server-id = 3
replicate-do-db = testdb

Тепер зупинимо реплікацію на першій репліці:
mysql@replica-1> stop slave;

Репліка продовжить працювати нормально, проте дані на ній вже не будуть актуальними. Подивимося статус та запам'ятаємо позицію майстра, до якої репліка дійшла перед зупинкою реплікації:
mysql@replica-1> SHOW SLAVE STATUS\G

Нам потрібні будуть значення Master_Log_File та Exec_Master_Log_Pos:
Master_Log_File: mysql-bin.000004
Exec_Master_Log_Pos: 155

Створимо дамп БД та продовжимо реплікацію на першій репліці:
mysql@replica-1> START SLAVE;

Відновимо дані із дампа на другій репліці. Потім увімкнемо реплікацію:
mysql@replica-2> CHANGE MASTER TO MASTER_HOST="192.168.1.101", MASTER_USER="replication", MASTER_PASSWORD="password", MASTER_LOG_FILE="mysql-bin.000004", MASTER_LOG_P;
mysql@replica-2> START SLAVE;

Значення MASTER_LOG_FILE та MASTER_LOG_POS — це відповідно значення Master_Log_File та Exec_Master_Log_Pos з результату команди show slave status на першій репліці.
Реплікація має розпочатися з тієї позиції, на якій було зупинено першу репліку (і відповідно створено дамп). Таким чином, ми матимемо дві репліки з ідентичними даними.

Об'єднуємо репліки

Іноді виникає така ситуація: на майстрі існує дві БД, одна з яких реплікується однією репліці, а друга — іншою. Як налаштувати реплікацію двох БД на обох репліках, не роблячи їхні дампи на майстрі та не вимикаючи його з роботи? Досить просто, з використанням команди "start slave until".
Отже, у нас є master з базами даних testdb1 та testdb2, які реплікуються відповідно на репліках replica-1 та replica-2. Налаштуємо реплікацію обох БД на replica-1 без зупинки майстра.
Зупинимо реплікацію на replica-2 командою та запам'ятаємо позицію майстра:
mysql@replica-2> STOP SLAVE;
mysql@replica-2> SHOW SLAVE STATUS\G
Master_Log_File: mysql-bin.000015
Exec_Master_Log_Pos: 231

Створимо дамп БД testdb2 та відновимо реплікацію (на цьому маніпуляції з replica-2 закінчилися). Дамп відновимо на replica-1.

Ситуація на replica-1 така: БД testdb1 знаходиться на одній позиції майстра і продовжує реплікуватися, БД testdb2 відновлено з дампи з іншої позиції. Синхронізуємо їх.

Зупинимо реплікацію та запам'ятаємо позицію майстра:
mysql@replica-1> STOP SLAVE;
mysql@replica-1> SHOW SLAVE STATUS\G
Exec_Master_Log_Pos: 501

Переконаємося, що в конфізі на replica-1 у секції вказано ім'я другої БД:
replicate-do-db = testdb2

Перезавантажимо MySQL, щоб зміни в конфізі набули чинності. До речі, можна було просто перезавантажити MySQL, не зупиняючи реплікацію — з лога ми дізналися б, на якій позиції майстра реплікація зупинилася.

Тепер проведемо реплікацію з позиції, де було припинено replica-2 до позиції, де ми щойно призупинили реплікацію:
mysql@replica-1> CHANGE MASTER TO MASTER_HOST = "192.168.1.101", MASTER_USER = "replication", MASTER_PASSWORD = "password", MASTER_LOG_FILE = "mysql-bin.000015", MASTER_LOG_P
mysql@replica-1> start slave until MASTER_LOG_FILE="mysql-bin.000016", MASTER_LOG_POS=501;

Реплікація закінчиться, як тільки репліка дійде до вказаної позиції в секції until, після чого обидві наші БД будуть відповідати одній і тій же позиції майстра (на якій ми зупинили реплікацію на replica-1). Переконаємося у цьому:
mysql@replica-1> SHOW SLAVE STATUS\G
mysql@replica-1> START SLAVE;
Master_Log_File: mysql-bin.000016
Exec_Master_Log_Pos: 501

Додамо до конфіг на replica-1 у секції імена обох БД:
replicate-do-db = testdb1
replicate-do-db = testdb2

Важливо: кожна БД має бути вказана на окремому рядку.
Перезавантажимо MySQL і продовжимо реплікацію:
mysql@replica-1> CHANGE MASTER TO MASTER_HOST = "192.168.1.101", MASTER_USER = "replication", MASTER_PASSWORD = "password", MASTER_LOG_FILE = "mysql-bin.000016", MASTER_LOG_P
Після того, як replica-1 наздожене майстер, зміст їхньої БД буде ідентичний. Об'єднати БД на replica-2 можна або так, або зробивши повний дамп replica-1.

Рокування майстра та репліки

Переключити репліку в режим майстра буває необхідно, наприклад, у разі відмови майстра або під час проведення технічних робіт. Для можливості такого перемикання необхідно налаштувати репліку подібно до майстра, або зробити її пасивним майстром.

Включимо ведення бінарних логів (додатково до relay-бінлогів) у конфізі в секції:
log-bin = /var/lib/mysql/mysql-bin

І додамо користувача для ведення реплікації:
mysql@master> GRANT replication slave ON 'testdb'.* TO 'replication'@'192.168.1.101′ IDENTIFIED BY "password";

Пасивний майстер веде реплікацію як і звичайна репліка, але, крім цього, створює бінарні логії — тобто ми можемо розпочати реплікацію з нього. Переконаємося у цьому командою "show master status":
mysql@replica> SHOW MASTER STATUS\G
File: mysql-bin.000001
Position: 61
Binlog_Do_DB:
Binlog_Ignore_DB:

Тепер, щоб перевести пасивний майстер на активний режим, необхідно зупинити реплікацію у ньому і включити реплікацію колишньому активному майстрі. Щоб у момент перемикання дані не були втрачені, активний майстерпотрібно заблокувати на запис.
mysql@master> FLUSH TABLES WITH READ LOCK
mysql@master> SET GLOBAL read_only = ON;
mysql@replica> STOP SLAVE;
mysql@replica> SHOW MASTER STATUS;
File: mysql-bin.000001
Position: 61
mysql@master> CHANGE MASTER TO MASTER_HOST = "192.168.1.102", MASTER_USER = "replication", MASTER_PASSWORD = "password", MASTER_LOG_FILE = "mysql-bin.000001", MASTER_LOG_POS =
mysql@master> start slave;
Все, так ми змінили активний майстер. Можна зняти з колишнього майстра блокування.

Висновок

Ми трохи розібралися в тому, як налаштовувати реплікацію MySQL і виконувати деякі основні операції. На жаль, за рамками статті залишилися такі важливі питання:

  • усунення одиничних точок відмови (SPF, Single Points of Failure). При використанні єдиного сервера MySQL його відмова призводила до відмови всієї системи. При використанні кількох серверів, відмова будь-якого з них призведе до відмови системи, якщо ми спеціально не подбаємо про це. Нам потрібно передбачити обробку ситуації з відмовою майстра та репліки. Один із існуючих засобів — MMM, однак, вимагає доопрацювання напилком.
  • балансування навантаження. При використанні кількох реплік нам було б зручно використовувати прозорий механізм балансування, особливо якщо продуктивність реплік неоднакова. Під Linux можна використовувати стандартне рішення - LVS.
  • зміна логіки роботи програми. В ідеальній ситуації запити на читання даних треба направляти на репліки, а на зміну — на майстер. Однак, через можливе відставання реплік, така схема часто непрацездатна і необхідно виявляти такі запити на читання, які все ж таки повинні виконуватися на майстрі.
Сподіваюся висвітлити ці питання у подальших статтях.
Дякую за увагу!

Теги: Додати теги

Моя доповідь призначена для тих людей, які знають слово "реплікація", навіть знають, що в MySQL вона є, і, можливо, один раз її налаштували, 15 хвилин витратили та забули. Більше про неї вони нічого не знають.

У доповіді не буде:


Все це є в Інтернеті, синтаксис розуміти немає.

Ми трохи пройдемося з теорії, спробуємо пояснити, як це все працює всередині, а після цього ви з потрійними силами зможете самі пірнути в документацію.

Що таке реплікація у принципі? Це копіювання змін. Ми маємо одну копію БД, ми хочемо з якоюсь метою ще одну копію.

Реплікація буває різних видів. Різні осі порівняння:

  • ступінь синхронізації змін (sync, async, semisync);
  • кількість серверів запису (M/S, M/M);
  • формат змін (statement-based (SBR), row-based (RBR), mixed);
  • теоретично модель передачі змін (push, pull).

Забавний факт - якщо трохи задуматися, реплікація нам теоретично допомагає з принципових міркувань скейлити лише читання. Ось такий дещо неочевидний висновок. Це тому, якщо у нас на ту саму копію даних треба налити певну кількість змін, і ця певна копія даних обслуговується одним і тим же сервером, то цей сервер здатний витримати певну кількість апдейтів на секунду, і більше туди не залити. Здатний сервер оновити 1000 записів за секунду, а 2000 – не здатний. Що зміниться від того, що ти поставиш до цього сервера репліку, неважливо, в режимі майстер-слейв чи майстер-майстер? Чи зумієш ти на цю репліку налити другу тисячу апдейтів? Правильна відповідь – ні.

На репліку в режимі майстер-майстер ти, звичайно, зумієш налити додаткових апдейтів, інша справа, що коли вони не прилетять на перший майстер і спробують на ньому зробити другу тисячу апдейтів, то ємності вже не вистачить. Треба розуміти і не змішувати два майже очевидні моменти, що реплікація, як би, про одне, а те, що дані треба дробити, і якщо треба скейлити не читання, а записи, доведеться робити щось інше, а реплікація не дуже врятує .

Тобто. реплікація – це більше прочитання.

Для синхронізації.

Синхронізація – гарантія наявності та доступності. Доступності в тому сенсі, що у нас commit пройшов, транзакція зафіксувалася, все добре, ці дані видно одній або декільком нодам у кластері, вони можуть брати участь у наступних запитах. Наявність це те, що дані, в принципі, є більш ніж на одному сервері, але, можливо, транзакція не програлася і не доступна.

Тут немає рефрена "commit закінчився успішно, що це означає?" Синхронний commit означає, що з нас локальний і віддалений (хоча однією репліці) закінчився, тобто. ми щось закоммітили на машину, якщо у нас синхронний режим реплікації, то ці зміни успішно закомітілися, вони помітні для подальших запитів на локальній машині, на віддаленій машині (хоча б на одній) теж видно. Це означає, що й трапилася стандартна позаштатна ситуація, тобто. в один і серверів прилетів брухт і пробив все наскрізь - від процесора до гвинта, то, незважаючи на це, дані не тільки скопійовані на якийсь віддалений сервер, але ще, до того ж, можуть миттєво, без якихось додаткових затримок, брати участь у наступних транзакції.

Це все загальна термінологія, ніяк не пов'язана з MySQL. У будь-якій розподіленій системі воно буде влаштоване так.

Асинхронний commit – жодних додаткових гарантій, як пощастить.

Напівсинхронний commit - приємне проміжне рішення, це коли у нас локальний commit пройшов, про віддалений commit нічого не відомо - може, слейв наздогнав, а, може, і не наздогнав, але щонайменше нам прийшло підтвердження, що ці дані куди- то полетіли і там прийняті і, мабуть, записалися.

Про сервер для запису. Які бувають види реплікації?

Master-slave classic, зміни всі ллються на один сервер, після цього копіюються на масу реплік.

Master-master true – коли зміни ллються на купу майстрів одночасно і якимось чином з одного на інший, з іншого на третій і між ними всіма, що породжує ряд радощів, і ряд автоматичних проблем. Зрозуміло, що коли в тебе є одна "золота копія" і з неї кілька реплік, які повинні (в ідеалі – миттєво) повторювати цю "золоту копію", то все порівняно просто з точки зору того, як дані сюди-туди ганяти і що робити на кожній конкретній копії. З master-master починається цікавий "головний біль", причому, підкреслюю, не конкретно у випадку MySQL, а суто теоретичний. Як же бути, якщо на двох нодах одночасно спробували прогнати одну й ту саму транзакцію, яка змінює ті самі дані, причому, змінює їх, для простоти прикладу, по-різному. Зрозуміло, що одночасно ці дві зміни ми не можемо застосувати. На момент, коли ми на одній ноді починаємо щось змінювати, на другій ноді поки що нічого немає. Конфлікт. Одну із транзакцій доведеться відкочувати. До того ж починаються окремі "танці" з звірянням годинників і т.п.

Цікавий момент - навіть варіант, коли у вас зрештою всі зміни з усіх майстрів повинні поступово поширитися скрізь, все одно не допоможе тому самому write bandwidth. Прикро, але так.

Приємний варіант - під назвою "Master-slave + routing запитів". Приємний він тим, що всередині програмувати просто, ти маєш одну основну копію, ти її реплікуєш на купу машин. Це набагато простіше, ніж у майстер-майстер середовищі, коли всі рівноправні і т.д., але з точки зору програми все одно виглядає так, ніби точок запису багато. Ти приходиш на будь-яку ноду, вона знає, куди тебе зароутити, і успішно роутіт. Ну, та читання масштабуються – ось воно щастя реплікації. Читати можна з усіх точок все і завжди.

Тепер ближче до баз даних, "чарівних" форматів statement-based, row-based і т.д. Формат змін.

Що робити? Можна надсилати самі запити, а можна надсилати лише змінені рядки. Наголошую - поки ми ще не пірнули в нетрі MySQL, цим може займатися будь-яка СУБД, в якій є запити, що породжують велику (або не дуже) кількість змін, тобто. оновлюють багато даних. Виникає питання – а що конкретно копіюватимемо? Можна самі запити сюди-туди між нодами ганяти, а можна ганяти тільки змінені дані. Цікаво, що так і так дуже погано! Можна ще намагатись змішувати.

Ще один пункт про те, які бувають реплікації. Про модель поширення. Напевно, десь досі ще не повністю вимерла модель Push-based, коли та нода, яка внесла зміни, та й зобов'язана розсилати їх по всіх інших нодах. З точки зору програмування та відстеження state"ів це та ще морока. Тому рулить Pull-based. Забирати апдейти з тієї чи іншої ноди - це набагато простіше запрограмувати, ніж на одній ноді стежити за хаотичним кластером своїх реплік.

Деякі загальні терміни запровадили. Переходимо до того, як зробили MySQL.

MySQL, сам собою, це якийсь обман. Є логічний шар під назвою MySQL, який займається всякими загальними та ізольованими від зберігання даних справами – мережа, оптимізатор, кеші тощо. Конкретний фізичний шар, який відповідає за зберігання даних, лежить на нижче. Є кілька вбудованих, є плагінами, що ставляться. Але навіть убудовані MyISAM, InnoDB і т.д. живуть на фізичному шарі. Плагінна архітектура - це кльово, можна підчепити новий двигун, але миттєво виникає якась неоптимальність. В принципі, транзакційні write-ahead log"і (WAL), які фізичний шар зберігання все одно пише, було б добре використовувати для реплікації, і якщо система знає про те, що є певний фізичний рівень, або досить добре пов'язана з цим фізичним рівнем , то можна було б окремий лог на логічному рівні не писати, а використовувати той самий WAL.Але у MySQL це неможливо концептуально, або, якщо поміняти інтерфейс в PSE так, щоб стало можливо концептуально, то буде дуже багато роботи.

Реплікація реалізована лише на рівні самого MySQL. У цьому є і хороше - крім одного лога у вигляді глибоко внутрішніх даних двигуна зберігання, є більш-менш логічний лог, можливо, на рівні statement"ів, який ведеться окремо від цього движка. А це "зайва" безпека і т.д. плюс, оскільки ніяких обмежень усередині немає, можна робити будь-який креатив типу заміни двигуна "на льоту".

У ведених термінах MySQL 4.1 було реалізовано: master-slave, pull-based, строго async і строго SBR. Якщо ви застрягли у давній епосі 4.х, то, мабуть, у вас все погано. Версіям 5.х вже мало не 10 років - настав час і оновитися.

Кумедно простежувати за версіями, як люди наступали на всілякі граблі і, коли зробити вже нічого не можна було, прикручували до цих граблів нові граблі, щоб життя було не таке болюче. Так, у версії 5.1 прикрутили RBR, щоб компенсувати неминучі проблеми з SBR, та прикрутили mixed режим. У версії 5.6 прикрутили ще приємні штуки: semi-sync, delayed slave, GTID.

Ще один момент. Оскільки MySQL - це якийсь загальний шар, з одного боку, і купа pluggable двигунів, з іншого боку, в тому числі, вбудованих, там є з певного моменту божественний NDB cluster, про який розповідають круте. Там є повністю синхронна майстер-майстер реплікація, дуже доступна in-memory БД... Але є один нюанс – як тільки починаєш шукати людей, які в продакшені використовують NDB cluster, таких людей перебуває вкрай мало.

Чим займається майстер, коли ви вирішили включити реплікацію? На майстрі відбувається досить мало додаткових рухів. Як завжди, ми по мережі приймаємо запити, парсемо їх, ганяємо транзакції, фіксуємо їх і т.д. На додаток до цього, логічно MySQL майстер починає вести binary log - файл, не зовсім текстовий, в який сиплються всі поспіль зміни. Також майстер вміє розсилати ці логи по мережі. Все це дуже просто і начебто працює.

Чим займається слейв? Зміни на слейв краще не надсилати, тому що можна потрапити в незрозуміле. У слейва трохи більше роботи. Крім того, щоб вести один додатковий лог і за запитом його розсилати, ще є тред, який ходить до віддаленого майстра, можливо, навіть не до одного, і качає звідти binary log". Рішення "давайте ходити до кількох віддалених майстрів і з них Просто фізично копіювати файли по SCP не можна, вже виходить на сервері один лог, в ньому свої позиції, локально ми їх по сітці тягнемо, складаємо в окремий лог, ще окремий тред бігає і намагається програвати ці локальні логи.Найдужче, на мій погляд, полягає в тому, що аж до версії 5.6 ідентифікація тієї чи іншої транзакції в лозі відбувалася на ім'я файлу і позиції на майстрі.

Ось шлях запису, який простенький insert проходить без реплікації:


Додаток скінчився до сервера, поклав у таблицю та відбій.

З реплікацією виходить кілька додаткових кроків:


Додаток-письменник так само йде до майстра, але на додачу ці дані потрапляють у тому чи іншому вигляді в binary log, потім гойдаються по мережі в relay log, потім з relay log"а поступово реплеються (якщо нам пощастило, і слейв не кладе, реплеются відразу) в таблицю на слейве, після чого все доступно в читачі.

Що конкретно потрапляє до binary log, залежить від налаштувань SBR/RBR/mixed. Звідки це все зростає? Уявімо себе базою даних. Нам прилетів простий запит "онови один конкретний запис" – UPDATE users SET x=123 WHERE id=456

Що записати в binary log? В принципі, однаково, насправді. Можемо коротенький запит записати, або (а він оновив один запис) можемо записати зміну якимось чином у тому чи іншому форматі.

Інша ситуація. Уявимо, що нам прилетів той самий запит, який сам собою маленький, а даних змінює багато – UPDATE users SET bonus=bonus+100

Тут ефективний варіант один - писати сам запит, тому що запит - рівно 32 байти, а записів він може оновити довільну кількість - 1000, 100000, 1000000, скільки завгодно ... Неефективно писати змінені записи в балку.

А що станеться, якщо ми в ліг помістимо такий нехитрий запит "давайте відключимо всіх користувачів, які давно не логінилися" - UPDATE users SET disabled=1 WHERE last_login

Раптом настає жах. Проблема в тому, що якщо ідеально среплікувати сам запит, то, по-перше, час ніколи не синхронно між двома нодами, крім цього, за рахунок того, що шлях запису такий довгий, в момент реплею цей "NOW" розійдеться-таки. Репліка раптово розходиться з майстром, і всі наступні зміни, формально кажучи, вже небезпечні, можуть призвести до чого завгодно.

Взагалі кажучи, для таких запитів, незалежно від кількості змінених даних, в ідеалі треба копіювати самі рядки. У даному конкретному випадку можна самі рядки не копіювати, а зафіксувати константу і в лог написати не "NOW", а конкретний timestamp, який був використаний майстром на момент реплікації.


Смішні факти, які випадково дізнаєшся, пірнаючи в нетрі реплікації. Причому пірнати можна неглибоко – нариваєшся на них стразу. У випадковому порядку вони такі:

  • майстер багатострумовий, а слейв – ні. Зрозуміло, що якщо майстер наливає навантаження чотири ядра, слейв це навантаження в одне ядро ​​наливати не встигає. Все досить погано;
  • стан слейва визначається іменем позиції у файлі майстра. Вдумайтеся - стан однієї ноди в кластері визначається ім'ям файлу і позицією в цьому файлі на іншій ноді кластера, з якої може статися будь-що!
  • "рятівний" RBR. Виявляється, за умовчанням туди пишуться повні before/after row image, тобто. ми змінили одну колонку у п'яти-кілобайтному рядку, оп! - 10 Кб трафіку і байтів 20-40 огорож на цей рядок, потім оп! - їде такий жирний рядок попередньої версії, оп! – їде після цього версія із новими значеннями. Адміністратори виють хором! Тим не менш, це просто офігенно з точки зору деяких збочених додатків, наприклад, зовнішніх читалок, які намагаються підчепитися до сервера MySQL, з нього витягувати дані і робити з ними щось, наприклад, пхати їх у повнотекстовий індекс. Наскільки це погано з точки зору адміністрування бази, в якій одна зміна на три байти породжує 10 Кб трафіку на гвинті, а потім 10 Кб трафіку по мережі на кожного слейву, настільки ж це добре для будь-яких систем типу повнотекстового пошуку, як Sphinx, у яких немає локальної копії даних, а MySQL з нуля імплементувати немає жодного бажання. У MySQL 5.6 схаменулися і зробили binlog_row_image (але по дефолту full, а не minimal або noblob).

Коротше кажучи, влаштовано все не хитро - палиця, мотузка, один лог, другий лог. І навіть у цьому лозі "дитячі" хвороби досить кумедні:


Для людини, яка використовує реплікацію два дні, все це страшно та важко. Але, знаючи, наскільки вона нехитро влаштована, зрозуміло, як з нею жити:

  • насамперед, не віримо дефолтам;
  • уважно дивимося на налаштування, думаємо, чого хочемо - SBR, RBR і т.д.

І краще відразу налаштувати, щоби потім не розбирати дивний фарш.

У ситуації "протух лог, розійшлася позиція, невідомо, що відбувається" є певний інструментарій - дивимося event"и, намагаємося зрозуміти, яка транзакція вже проскочила, яка - ні, чи можна всю цю справу врятувати або відновити і т. д. Якщо GTID "Заздалегідь зуміли включити, то життя стає простіше.

Інший момент спостереження за реплікацією. Цікаво подивитися, як внутрішній кривий пристрій провокує не те, що конкуренцію, а створення додаткових продуктів. "Чарівний" Tungsten Replicator, кажуть, добре вирішує завдання під назвою "однопотоковий слейв - це погано", а якби не вроджені складнощі, не було б додаткового продукту, який дозволяє користуватися цим механізмом, переливати дані в інші системи, з одного боку, і заразом вирішувати ряд проблем, вбудованих у існуючу систему, з іншого боку.

Як завжди, радити неможливо. Комусь допомагає, хтось сильно плюватиметься. Але, кажуть, є ситуації, в яких з неминучим однопоточним лагом добре справляється Tungsten. Я впевнений, є ще різні цікаві фокуси, але внутрішній однопотоковий слейв - це важко.

Що робити, якщо ви навіщось використовували репліки як бекап? Я вважаю, треба битися головою об стіну, тому що репліка та бекап – це дві різні штуки. Тим не менш, якщо ви креативні пацани і використовуєте досить нову версію, delayed replication вас рятує, з одного боку, але з іншого боку, якщо ви не робите повноцінних бекапів, вас все одно нічого не врятує.

Далі ще один елемент креативу. Неважко уявити ситуацію, коли майстер забив логами весь 10 PB хмарний диск або забив розсиланням цих логів усю мережу, при цьому 90% цих оновлень нам не потрібні, тому що нам цікаво реплікувати, наприклад, одну таблицю прицільно або одну базу прицільно, а за замовчуванням все валиться валом у бінарний лог – всі зміни по всіх базах, по всіх таблицях, по всьому. Рішення знову вражає своєю креативністю. З одного боку, є чотири налаштування – (binlog | replicate)_ (do | ignore)_db, які дозволяють фільтрувати на майстрі – що запишеться в балку, а що проігнорується. На слейві, відповідно, дозволяє робити те саме. Тобто. на майстрі ми можемо відфільтрувати те, що потрапляє в binary log - в цю вирву, яка потім зливається в мережу, а на слейві, відповідно, ми можемо поставити вхідний фільтр на те, що прилітає з мережі. Або писати на диск лише частину даних, а потім на слейві реплеїти, знову ж таки, лише частину даних. Несподівано навіть у цій нехитрій історії настає жах, тому що комбінація - використовуємо одну БД, а апдейтим таблицю в інший БД через цікавий синтаксис - вона поводиться якось ... А як саме вона поведеться - невідомо, т.к. різні фільтри спрацьовують у різні моменти.

Вбудованих приємних штук під назвою "перевибори майстра, якщо він раптово здох" немає, треба піднімати руками. Відсутність інструментів для управління кластером – це, на мою думку, добре – породжує конкуренцію, породжує створення додаткових продуктів. Справді, якби в звичайному MySQL ідеально працювала дуже кльова майстер-майстер реплікація, або хоча б автоматичне підняття після збоїв, то навіщо була б потрібна всяка Galera, Рercona/MariaDB Cluster і т.д.?

Ще трохи фокусів. Цікава реалізація реплікації, яка проста як палиця і мотузка, без будь-яких перевірок, з одного боку, і без будь-яких інструментів, щоб приємніше змінювати кластер слейву, що реплікується, з іншого боку. Це погано. Зате можна вручну ліпити з цього такі цікаві конфігурації, що здригнуться всі, хто потім прийде і за вами це розбиратиме.

Зміна №1. Майстер-майстер «на коліні» в стилі MySQL робиться так:


Що лякає – скільки у світі ідіотів! Погуглите "Майстер-майстер MySQL реплікація" - кожне друге посилання ось таке. Пекло та голокост.

Фокус №2 - catch-all slave - приємніше. Жодних непотрібних перевірок немає - що з кого прилітає, кому потрапляє, і що з цим робити. За рахунок цього можна зробити кумедні штуки типу слейва, на який або прицільно зливається частина даних з купи серверів, або прицільно зливаються всі дані з усіх серверів - сервер з усіма бекапами. Але, повторюся, реплікація є, тобто. є якийсь базовий інструмент, який копіює таблицю А замість і все.

Ну і, нарешті, фокус №3 – підміняємо всяке. Згадуємо, що реплікація живе на логічному рівні, що ніяк не пов'язане з фізичним рівнем зберігання. За рахунок цього можна дуже цікаво дивувати. Можна міняти двигун «на льоту» з незрозумілими цілями – ось true story, що, мовляв, реплікація з InnoDB баз у MyISAM таблиці просто заради того, щоб повнотекстовий пошук працював хоч якось. Є креативний фінт під назвою "зміна схеми через реплікацію". У чому жир розуміти відмовляюся, але бувають і такі фокуси. Ну і є зрозумілий і цікавий режим роботи під назвою "параноїдальний апгрейд версії через реплікацію".

У ході доповіді ми дізналися:


Тим не менш, з цим пеклом можна жити, якщо хоча б приблизно розуміти, як воно влаштоване.

Основний посил у тому, що:


У 2015 році на конференції HighLoad++ Junior Андрій Аксьонов прочитав нову версію своєї доповіді про влаштування реплікації в MySQL. Її ми також розшифрували і у своєму блозі.

Сподобалася стаття? Поділитися з друзями: