Налаштування реплікації баз даних MySQL. Налаштування реплікації Master-Slave в MySQL Інші корисні налаштування бінарного логу

Налаштування реплікації баз даних MySQL. Налаштування реплікації Master-Slave в MySQL Інші корисні налаштування бінарного логу

Для успішного використання реплікації в MySQL необхідно:

  • Переконається, що на сервер, що виступає у ролі Slave, встановлена ​​версія MySQL >= версії, встановленій на Master. Реплікація можлива і в зворотному порядку, з Master з новішою версією на Slave з більш старою, але працездатність такого варіанту не гарантується.
  • Перевірити підключення з Slave-сервера MySQL на Master (# mysql -hMASTERHOST -uroot -p), оскільки воно може бути закрите в firewall.

Master-slave реплікація однієї бази MySQL

Це простий приклад master-slave реплікації однієї бази MySQL. Тим хто це робить вперше, слід почати з цього прикладу і точно дотримуватися інструкцій.

Для початку потрібно прописати різні id для Master і Slave серверів. На Master-серверіпотрібно включити бінарний журнал (log-bin), вказати БД для реплікації та створити користувача підлеглого сервера, через якого slave-сервер отримуватиме дані з master`а. на slave-серверівключається релейний лог (relay-log), вказується БД для реплікації та запускається slave-реплікація.

MASTER: дії, які виконуються на Master-сервері MySQL.

Відредагувати my.cnf – конфігураційний файл MySQL. Його розташування залежить від операційної системи та налаштувань самої MySQL. У my.cnf до секцій додаються такі параметри:


server- id= 1

# Шлях до бінарного лога.
# Записується назва файлу без розширення, оскільки розширення все одно буде встановлено
# MySQL-сервером автоматично (.000001, .000002 і т.д.)
# Розташовувати mysql-bin бажано в корені директорії, де зберігаються всі БД,
# Щоб уникнути проблем із правами доступу.
log-bin =/ var/ lib/ mysql/ mysql- bin

# Назва БД MySQL, яка реплікуватиметься

Після модифікації my.cnf слід перезапустити MySQL. У директорії для зберігання журналу бінарних логів (log-bin) має з'явитися один або кілька файлів mysql-bin.000001, mysql-bin.000002, ….

Тепер потрібно підключитися до MySQL як користувач з максимальними правами та створити користувача (rpluser_s500) з паролем (замінити PASSW), через якого Slave-сервер отримуватиме дані про оновлення БД:

mysql> GRANT replication slave ON * .* TO "rpluser _ s500"@"% " IDENTIFIED BY "PASSW";
mysql> FLUSH PRIVILEGES ;

$ mysqldump -- master - data - hHOST - uUSER - p dbreplica > dbreplica.sql

Дамп можна знімати з БД під навантаженням, але слід врахувати, що якщо БД велика, то на час запису дампа БД не буде доступна на запис.

SALVE: дії, які виконуються на Slave-сервері MySQL.

Насамперед потрібно провести правки my.cnf у секції:

# Ідентифікатор Master сервера (число від 1 до 4294967295)
server-id = 500

# Шлях до релей-логу, в якому зберігаються дані, отримані від Master-сервера
# Вимоги такі самі, як і до бінарного лога.
relay-log =/ var/ lib/ mysql/ mysql- relay- bin
relay-log-index =/var/lib/mysql/mysql-relay-bin.index

# Ім'я бази, до якої будуть записуватися всі зміни,
# що відбуваються в БД з тим самим ім'ям на Master-сервері
replicate- do- db= "dbreplica"

Після модифікації my.cnf – перезапустити MySQL.

mysql> CREATE DATABASE dbreplica

Тепер у неї потрібно залити дамп:

$ mysql - uROOT - p dbreplica< dbreplica.sql

Далі налаштовуємо підключення до Master-серверу, де MASTER_HOSTNAME_OR_IP замінюється на адресу або ip MySQL master сервера, а MASTER_USER та PASSWORD - облікові дані користувача, створеного на Master-сервері для підключення зі Slave:

mysql> CHANGE MASTER TO MASTER_HOST = "MASTER _ HOSTNAME_ OR_ IP", MASTER_USER = "rpluser _ s500", PASSWORD = "PASSW";

Після запуску цього запиту, в директорії, де зберігаються бази даних, створюється файл master.info, куди записуються дані про підключення до Master.

Тепер для початку реплікації залишилося відправити запит до MySQL:

mysql> START SLAVE;

Після цього, якщо все пройшло успішно, можна спостерігати, як усі зміни у БД на Master-сервері з'являються у БД на Slave.

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

Налаштування бінарного лог-файлу (log-bin)

Бінарний лог MySQLвикористовується для ведення журналу змін, що відбуваються у базах даних сервера. Для реплікації він повинен бути обов'язково включений на Master-сервері, на Slave-серверах його варто використовувати тільки якщо Slave є одночасно і Master`ом для іншої підлеглої MySQL. Log bin включається, шляхом додавання параметра mysql.cnf, секції :

log-bin = mysql-bin

У прикладі налаштувань: "Master-slave реплікація однієї бази MySQL" було включено бінарний лог всім баз даних MySQL. Якщо потрібно вести лог тільки для певних баз даних, наприклад DB_NAME1 і DB_NAME2 в my.cnf майстри потрібно додати опції binlog-do-db:

binlog- do- db= "DB _ NAME1"
binlog- do- db= "DB _ NAME2"

Тобто потрібно перерахувати всі назви БД, де для кожної БД свій рядок з параметром binlog-do-db. Антонім цього оператора є binlog-ignore-db="DB_NAME", який вказує MySQL, що потрібно заносити в лог усі бази даних, крім тих, що вказані в параметрах binlog-ignore-db.

Якщо вказати бази даних, через кому, наприклад:

Неправильне використання параметра binlog-ignore-db!

binlog-ignore-db = "DB _ NAME3, DB_ NAME4"

то на перший погляд все буде працювати як потрібно - ніяких помилок немає, але насправді бази DB_NAME3 і DB_NAME4 не будуть виключені з бінарного журналу: MySQL буде вважати, що "DB_NAME3, DB_NAME4" це одна база даних з ім'ям "DB_NAME3, DB_NAME4 " (Тобто в імені БД знаходиться кома і пробіл)!

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

Параметр, відповідальний формат зберігання даних бінарним журналом - binlog_format, який починаючи з версії MySQL 5.1 може приймати 3 значення: STATEMENT (використовується за умовчанням у MySQL = 5.7.7) та MIXED.

STATEMENT – режим бінарного логу MySQL

STATEMENT- у цьому режимі в бінарний лог записуються звичайні SQL-запити на додавання, оновлення та видалення інформації з додатковими службовими даними. Відкривши такий лог у текстовому редакторі, можна знайти у ньому запити зміну даних у БД в текстовому форматі. Переваги використання binlog_format=STATEMENT: порівняно невеликий розмір файлу, можливість переглядати лог у mysqlbinlog або PHPMyAdmin`і. Недоліки ж таяться у використанні SQL-запитів, докладніше звідси нижче.

Припустимо, що до бінарного лога додаються дані лише для однієї БД з назвою users (binlog - do- db= "users"). Наступний запит, який безпосередньо стосується бази даних "users", не потрапить до бінарного журналу:

Приклад №1

USE clients;
UPDATE users.accounts SET amount= amount+ 5 ;

Така поведінка викликана тим, що за умовчанням використовується БД "clients", яка не логується в бінарному журналі як Statement.

Інший приклад, коли запит до БД, яка не вказана в binlog-do-db, потрапляє до бінарного журналу:

Приклад №2

USE users;
UPDATE clients.discounts SET percentage = percentage + 5;

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

І перший і другий запит може призвести до несподіваних наслідків при використанні реплікації на сервері Slave. У разі запиту з першого прикладу дані на Master і Slave серверах будуть різнитися: на майстрі amount=amount+5 виконано, на Slave - ні. При використанні другого запиту, на Slave буде надіслано запит на зміну даних у БД, яка не прописана у списку підлеглих, та Master-Slave реплікація: завершиться з помилкою, якщо БД clients не існує на слейві або... внесе зміни до таблиці бази даних якщо така є. Таким чином, при Master-Slave реплікації в режимі бінарного лога Statement, можна внести зміни до бази даних підлеглого сервера, яка не призначалася для реплікації!Які наслідки можуть призвести до таких змін, можна тільки здогадуватися, так що потрібно бути дуже обережним, використовуючи режим бінарного лога Statement.

Ще одна проблема, при використанні бінарного журналу в режимі Statement, може виявитися, якщо на сервері Slave налаштувати запис в бази даних з іменами, відмінними від оригіналу. Наприклад, проводиться реплікація однієї БД з майстра db_countries на слейв, де ця ж БД називається db_countries_slave (нове ім'я БД на Slave-сервері визначається параметром replicate-rewrite-db="db_countries->db_countries_slave", а для реплікації вже replicate-do-db="db_countries_slave"). Поки що на майстрі проводиться оновлення даних у БД з використанням USE db_countries і UPDATE names SET ..., все добре, але як тільки пройде запит, в якому буде вказуватися ім'я БД, наприклад: UPDATE db_countries.names SET ... реплікація на Slave зупиняється з помилкою: Table "db_countries.names" doesn"t exist" on query. Default database: "db_countries_slave". Query: UPDATE db_countries.names SET .... У режимі ROW такої проблеми немає.

ROW - режим бінарного логу

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

У бінарний лог записуються лише змінені дані для баз даних, які визначені за допомогою параметрів binlog-do-db або binlog-ignore-db. База даних за умовчанням не впливає на цю поведінку. Завдяки цьому після запитів з прикладу 1 дані про оновлення потраплять у бінарний лог, а ось sql з другого прикладу вже не буде записаний.

Більш детальний опис переваг і недоліків режимів Statement і Row можна отримати з офіційної документації англійською: 17.1.2.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication .

MIXED – режим бінарного логу

MIXED- Режим, в якому бінарний лог одночасно використовує 2 режими реплікації: Statement і Row для зберігання даних про різні запити. Докладніше дізнатися, як працює режим бінарного лога Mixed можна з офіційної документації англійською: 5.4.4.3 Mixed Binary Logging Format . Не можна сказати, що це ідеальний варіант, але якщо розуміти, як працює Mixed, його цілком можна застосовувати на практиці.

Автоматичне очищення бінарного лога - expire_logs_days

За замовчуванням бінарні логи ніколи не очищаються автоматично. Для автоочищення log-bin служить параметр expire_logs_days, в якому задається кількість днів, яке MySQL буде зберігати бінарний журнал.

Приклад автоматичного видалення бінарного лога, з дати створення якого пройшло понад 10 днів

expire_logs_days = 10

Інші корисні налаштування бінарного логу

Користувач для підключення Slave до Master

При Master-Slave реплікації, необхідний мінімум один обліковий запис користувача на Master-сервері, який використовуватиметься Slave для підключення. Вимоги до прав доступу такого облікового запису: єдиний привілей REPLICATION SLAVE - відкривати доступи до баз даних, таблиць або додавати будь-які інші привілеї - не потрібно. Один користувач із REPLICATION SLAVE може використовуватися різними підлеглими серверами для одночасного отримання даних із головного сервера, або можна для кожного підлеглого створити окремого користувача.

Не слід застосовувати для реплікації обліковий запис наділений будь-якими розширеними правами доступу. Логін та пароль для підключення до головного сервера зберігається у відкритому вигляді на підлеглому (файл master.info у каталозі з БД).

mysql> CREATE USER "replicat" @ "10.0.0.1" IDENTIFIED BY "pass" ;
mysql> GRANT REPLICATION SLAVE ON * .* TO "replicat" @ "10.0.0.1" ;

IP-адреса 10.0.0.1 – це ip Slave-сервера, потрібно замінити на реальну. У sql-запитах можна замінити IP-адресу на спеціальний символ %, тоді підключитися до майстра можна буде з будь-якого хоста, але з міркувань безпеки краще обмежиться реальною адресою підлеглого сервера.

Додаткові налаштування

Для максимально коректної реплікації баз даних, у яких використовуються таблиці типу InnoDB та транзакції, необхідно додати такі рядки до конфігурації Master-сервера (my.cnf секція):

innodb_flush_log_at_trx_commit=1
sync_binlog = 1

Моя доповідь призначена для тих людей, які знають слово "реплікація", навіть знають, що в 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. Її ми також розшифрували і у своєму блозі.

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

Це найпростіший спосіб встановлення підлеглого сервера, але він не єдиний. Наприклад, якщо вже є образ головного сервера, на головному сервері вже встановлений ID сервера і виконуються записи в журнал, підлеглий сервер можна встановити, не зупиняючи головний сервер і навіть не встановлюючи блокування оновлень (додаткову інформацію звертайтеся до розділу See section 4.10.7 Часто питання по реплікації .

Щоб стати справжнім гуру з реплікації MySQL, радимо спочатку вивчити, осмислити і випробувати всі команди, згадані в розділі See section 4.10.6 SQL-команди, що відносяться до реплікації . Необхідно також ознайомитися з опціями запуску реплікації з файлу my.cnf в розділі See section 4.10.5 Опції реплікації у файлі my.cnf .

  1. Переконайтеся, що на головному та підпорядкованому серверах встановлена ​​свіжа версія MySQL. Використовуйте версію 3.23.29 та вище. У попередніх релізах застосовувався інший формат двійкового журналу та були помилки, які були виправлені в новіших релізах. Велике прохання: будь ласка, не надсилайте повідомлення про помилки, не перевіривши, чи є ця помилка в останньому релізі.
  2. Встановіть на головному сервері окремого користувача для реплікації з привілеєм FILE (у версіях MySQL нижче 4.0.2) або REPLICATION SLAVE у новіших версіях MySQL. Цей користувач повинен також мати дозвіл підключатися з усіх підлеглих серверів. Якщо користувач буде виконувати лише реплікацію (рекомендується), йому не потрібно надавати будь-які додаткові привілеї. Наприклад, щоб створити користувача з ім'ям repl , який може мати доступ до головного сервера з будь-якого хоста, можна використовувати таку команду: mysql> GRANT FILE ON *.* TO repl@"%" IDENTIFIED BY " ";
  3. Завершіть роботу MySQL на головному сервері. mysqladmin -u root -p shutdown
  4. Створіть образ усіх даних на головному сервері. Найлегше зробити це (на Unix), створивши за допомогою tarархів усієї своєї директорії даних. Точне розташування директорії даних залежить від вашої інсталяції. tar -cvf /tmp/mysql-snapshot.tar /path/to/data-dir Користувачі Windows для створення архіву каталогу даних можуть використовувати WinZIP або іншу подібну програму.
  5. У my.cnf на головному сервері додайте записи до розділу запису log-bin та server-id=унікальний номер до розділу та перезапустіть сервер. Дуже важливо, щоб ID підлеглого сервера відрізнявся від ID головного сервера. Можна вважати, що server-id грає роль IP-адреси – він унікально ідентифікує сервер серед учасників реплікації. log-bin server-id=1
  6. Перезапустіть MySQL на головному сервері.
  7. Додайте в my.cnf на підпорядкованому сервері(ах) наступний фрагмент: master-host=master-user=master-password=master-port=server-id= замінюючи значення значеннями, що відповідають вашій системі. Значення server-id повинні бути різними на кожному сервері, який бере участь у реплікації. Якщо значення server-id не визначено, воно буде встановлено в 1, якщо також не визначено значення master-host , воно буде встановлено в 2. Зверніть увагу, що якщо значення server-id опущено, то головний сервер відмовлятиме з'єднання всім підлеглим серверам , а підлеглий сервер – відмовляти у з'єднанні головному серверу. Таким чином, опускати налаштування значення server-id можна лише у разі резервного копіювання з використанням двійкового журналу.
  8. Скопіюйте дані знімка в каталог даних на підпорядкованому сервері (ах). Впевніться у правильності привілеїв для файлів та каталогів. Користувач, від імені якого запускається MySQL, повинен мати можливість читати та записувати дані в них так само, як і на головному сервері.
  9. Перезапустіть підпорядкований сервер(и).

Після виконання зазначених дій підпорядкований сервер(и) повинен(и) приєднатися до головного сервера і підганяти свої дані під будь-які зміни, що відбулися на головному сервері після прийняття образу.

Якщо не встановлено ідентифікатор server -id для підлеглого сервера, до журнального файлу реєстрації помилок буде внесено таку помилку:

Warning: один повинен set server_id до non-0 value if master_host is set. The server will не act as a slave. (Попередження: якщо встановлено master_host, слід встановити server_id у ненульове значення. Сервер не працюватиме як підлеглий сервер.)

Якщо не встановлено ідентифікатор головного сервера, підлеглі сервери не можуть підключитися до головного сервера.

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

Після того як підлеглий сервер почне виконувати реплікацію, в тій же директорії, де знаходиться журнал реєстрації помилок, з'явиться файл `master.info". Файл `master.info" використовується підлеглим сервером для відстеження того, які записи двійкових журналів головного сервера оброблені. Не видаляйте і не редагуйте цей файл, якщо не впевнені, що це необхідно. Навіть якщо така впевненість є, все одно краще використовувати команду CHANGE MASTER TO.

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

Для чого можна використовувати реплікацію:
1. Розподіл навантаження між хостами підвищення продуктивності.
У такій схемі головний вузол буде виконувати операції читання та записи, вузли, які мають підписку на головному вузлі, будуть надавати базу для читання, таким чином, ми розвантажимо майстер сервер від операцій читання
2. Безпека даних та зручність обслуговування, оскільки підлеглий вузол містить дані тільки для читання, то зміна даних на передплатнику буде обмежена, зручність обслуговування – можливість запускати процеси, що обслуговують базу, не перериваючи роботу додатків.
3. Розподіл даних великі відстані. Можна створити копію даних на будь-якому хості незалежно від його розташування
Mysqlпідтримує такі методи реплікації:
Традиційний метод заснований на тиражуванні подій з бінарного файлу лога майстра і вимагає файли логів. Позиції між провідним та веденим серверами мають бути синхронізовані.
Метод із використанням глобальних ідентифікаторів транзакцій GTIDs (транзакційний метод)
Mysqlпідтримує такі типи синхронізації:
асинхронну (одностороння синхронізація)
напівсинхронну (частковий контроль передплатників)
синхронну (повний контроль передплатників)

Налаштування реплікації баз даних Mysql традиційний метод

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

Налаштування Майстра
my.iniповинен містити унікальний ідентифікатор – число від 1 до 2 до 32 ступеня – 1, server-id.
За промовчанням server-id=0, що означає не приймати підписки від підлеглих серверів

log-bin=mysql-bin
server-id=1

Цих двох рядків достатньо для запуску
Примітка: якщо використовується InnoDB, то додатково рекомендується внести
innodb_flush_log_at_trx_commit=1
sync_binlog=1

І потрібно перевірити, що не вимкнено можливість працювати з мережею не виставлено параметр skip-networking
Ведомий сервер підключається до головного, використовуючи ім'я користувача та пароль, тому на майстер сервері попередньо створюємо користувача
CREATE USER repl@%.mydomain.com IDENTIFIED BY slavepass;
GRANT REPLICATION SLAVE ON *.* TO repl@%.mydomain.com;

Дивимося стан
SHOW MASTER STATUS
Якщо раніше вже була запущена процедура створення бінарних журналів, то для таблиць InnoDB попередньо в одному з сеансів потрібно закласти таблиці
FLUSH TABLES WITH READ LOCK;
Якщо вийти з сеансу, блокування таблиць автоматично знімається
В іншому сеансі отримуємо значення імені binлога та позицію
Обидва значення є координатами реплікації при яких ведений сервер повинен почати читання з файлу в потрібному місці, щоб почати реплікацію.
Наступний крок залежить від того, чи є дані на веденому сервері, дані від майстра
Якщо вони є, то залишаємо таблиці залоченими, створюємо dump(це рекомендований спосіб при використанні InnoDB)
Дізнатись тип бази можна командою
mysqlshow -u mysql_user -p -i database-name
Якщо база зберігається в бінарних файлах, то допускається їхнє копіювання з ведучого на ведений сервер
Робимо dump
mysqldump --all-databases --master-data dbdump.db
для вибору баз mysqldump --databases --master-data dbdump.db
Параметр master-data автоматично додає CHANGE MASTER TOна підлеглому вузлі, якщо параметр не додавати, необхідно блокувати всі таблиці в сесії в ручну
Зняти блокування
UNLOCK TABLES;

Налаштування керованого вузлаа
Додаємо в my.ini server-id від особистий від майстра та від інших вузлів

server-id=2

Створюємо передплату
CHANGE MASTER TO
MASTER_HOST=master_host_name,
MASTER_USER=replication_user_name,
MASTER_PASSWORD=replication_password,
MASTER_LOG_FILE=recorded_log_file_name,
MASTER_LOG_POS=recorded_log_position;

При налаштуванні реплікації з існуючими даними потрібно передати знімок від ведучого до веденого перед початком реплікації
Використовуємо mysqldump
1.Запускаємо підлеглий вузол використовуючи --skip-slave-startпараметр, щоб реплікація не запускалася
2.Імпортуємо файл дампа
mysql fulldb.dump
3. Запускаємо процес передплати
START SLAVE;
Перевірка стану реплікації
SHOW SLAVE STATUS\G
Slave_IO_State: - поточний стан керованого пристрою
Slave_IO_Running: - Чи читається потік даних з майстра
Slave_SQL_Running: - чи працюють SQL запити, повинно бути yes

прикладНалаштуємо Майстер (провідний) сервер – ip 11.11.11.10 my.ini
[
mysqld] log-bin=mysql-bin server-id=1
Створюємо користувача mysql -u root -p GRANT REPLICATION SLAVE ON *.* TO replica@% IDENTIFIED BY password; FLUSH PRIVILEGES;
Далі блокуємо всі таблиці у базі даних FLUSH TABLES WITH READ LOCK;
Дивимося статус SHOW MASTER STATUS; Запам'ятовуємо ім'я файлу та позицію, їх будемо використовувати на Ведомому сервері для передплати

На Слейві В my.ini
log-bin=mysql-bin server-id=2

Створюємо передплату CHANGE MASTER TO MASTER_HOST=11.11.11.10, MASTER_PORT=3306,
MASTER_USER=replica, MASTER_PASSWORD=password,
MASTER_LOG_FILE=server-mysql-bin.000002,
MASTER_LOG_POS=1151664, MASTER_CONNECT_RETRY=10;
START SLAVE;
Статус реплікації SHOW SLAVE STATUS\G

З реплікацією серверів 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.
  • зміна логіки роботи програми. В ідеальній ситуації запити на читання даних треба направляти на репліки, а на зміну — на майстер. Однак, через можливе відставання реплік, така схема часто непрацездатна і необхідно виявляти такі запити на читання, які все ж таки повинні виконуватися на майстрі.
Сподіваюся висвітлити ці питання у подальших статтях.
Дякую за увагу!

 

 

Це цікаво: