digital-garden/_inbox/Репликация в MySQL.md

118 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
aliases:
tags:
- зрелость/🌱
date:
- - 2024-05-28
zero-link:
- "[[00 MySQL]]"
parents:
- "[[Репликация БД]]"
linked:
link: https://highload.guide/blog/asynchronous-replication.html
---
## Тезисы
- На slave можно реализовать другую схему БД, построить другие индексы.
- Можно использовать [libslave](libslave.md), чтобы "притвориться" репликой.
- Мастер многопоточен, а слейв - нет. Вроде исправлено в новых версиях SQL.
- В 5.6 версии можно реплицировать параллельно несколько БД
- В 5.7 версии можно реплицировать параллельно одни и те же таблицы
- Обязательно убедиться, что работают GUID идентификация транзакций.
***
**Репликация сильно зависит от версии MySql**
- Всегда логическая репликация, модель master-slave, pull распространение
- 4.1 = асинхронная, SBR, logposs
- 5.1 = +RBR, +mixed. Дефолт mixed
- 5.6 = +semisync, +mtslave (per-db), +slavedelay, +GTID
- 5.7 = + mtslave, +master-master (plugin), +default-RBR (image=full?!), groupcommit
## Схема работы репликации
![Архитектура MySQL](Архитектура%20MySQL.md#^42f122)
Такая плагинная архитектура позволяет устанавливать новый движок, но мгновенно возникает неоптимальность. В принципе, транзакционные write-ahead log'и (WAL), которые физический слой хранения все равно пишет, было бы хорошо использовать для репликации, и если система знает о том, что есть некий физический уровень, или достаточно хорошо сопряжена с этим физическим уровнем, то можно было бы отдельный лог на логическом уровне не писать, а использовать тот же самый WAL. Но у MySQL это невозможно концептуально, либо, если поменять интерфейс в PSE так, чтобы стало возможно концептуально, то будет очень много работы.
При включении репликации на логическом уровне MySQL мастер начинает вести binary log файл, в который сыплются все подряд изменения.
У слэйва чуть больше работы. Помимо того, чтобы вести один дополнительный лог(relay log) и по запросу его рассылать, еще есть поток, который ходит к удаленному мастеру, возможно, даже не к одному, и качает оттуда binary log'и. Еще отдельный поток пытается исполнять эти локальные логи.
![](Pasted%20image%2020240206200527.png)
**Процесс записи данных операции в MySQL**
- INSERT INTO test VALUES (123, 'hello')
- Записываем в таблицу на мастере mysqld
- Записываем в binary log на мастере
- Записываем в relay log на слейве
- таблица на слейве mysqld
Что конкретно попадает в binary log, зависит от настроек журнала.
Рабочие потоки ([MySQL Replication Threads](https://dev.mysql.com/doc/refman/8.0/en/replication-threads.html)):
- binlog dump thread. Сохраняет лог транзакций на master
- slave I/O thread. Спуливает изменения на slave с master
- slave SQL thread. Применяет изменения на slave
Варианты репликаций:
- [Statement Based Replication (SBR)](Statement%20Based%20Replication%20(SBR).md)
- [Row Based Replication (RBR)](Row%20Based%20Replication%20(RBR).md)
- [Mixed binlog format](Mixed%20binlog%20format.md)
MySQL не решает из коробки проблемы кластеризации. Из коробки нет переключений со slave на master если мастер сдох, распределения нагрузки и так далее. Можно решить дополнительным софтом:
- MHA (MySQL Master HA)
- MySQL Failover (Oracle)
- Orchestrator
## Фильтрация репликации
Можно реплицировать данные частично, но это стоит использовать осторожно. Например, это не работает с [Групповая репликация](Групповая%20репликация.md)
Опции:
- replicate_do_db
- replicate_ignore_db
- replicate_do_table
[MySQL - CHANGE REPLICATION FILTER Statement](https://dev.mysql.com/doc/refman/8.0/en/change-replication-filter.html)
![](Pasted%20image%2020240605091913.png)
***
- В InnoDB, заметьте, т.е. у нас архитектура разделяет репликацию выше, а storage engine ниже. Но storage engine, для того, чтобы репликация работала, должен, грубо говоря, замедлять insert'ы в таблицу.
- Другая проблема состоит в том, что мастер выполняет запросы параллельно, т.е. одновременно, а слэйв их может применять последовательно. Возникает вопрос а почему слэйв не может применять их параллельно? На самом деле, с этим все непросто. Есть теорема о сериализации транзакций, которая рассказывает, когда мы можем выполнять запросы параллельно, а когда последовательно. Это отдельная сложная тема, разберитесь в ней, если вам интересно и нужно, например, почитав по ссылке  [http://plumqqz.livejournal.com/387380.html](http://plumqqz.livejournal.com/387380.html).
- В MySQL репликация упирается в процессор. Это прекрасная картинка большой, мощный сервер, 12 ядер. Работает одно ядро, заодно занято репликацией. Из-за этого реплика задыхается. Это очень грустно.
Для того чтобы выполнять запросы параллельно существует группировка запросов. В InnoDB есть специальная опция, которая управляет тем, как именно мы группируем транзакции, как именно мы их пишем на диск. Проблема в том, что мы можем их сгруппировать на уровне InnoDB, а уровнем выше на уровне репликации этой функциональности не было. В 2010 г. Кристиан Нельсен из MariaDB реализовал такую фичу, которая называется Group Binary Log Commit. Получается, мы журнал повторяем на двух уровнях Storage Engine и репликация, и нам нужно таскать фичи из одного уровня на другой. Это сложный механизм. Более того, нам нужно одновременно консистентно писать сразу в два журнала two-phase-commit. Это еще хуже.
На следующей картинке мы видим два графика:
![](Pasted%20image%2020240528090119.png)
Синий график демонстрирует то, как масштабируется InnoDB, когда мы ему добавляем треды. Накидываем треды число транзакций, которые он обрабатывает, возрастает. Красная линия показывает ситуацию, когда включена репликация. Мы включаем репликацию и теряем масштабируемость. Потому что лог в Binary Log пишется синхронно, и Group Binary Log Commit это решает.
Грустно, что приходится так делать из-за разделения Storage Engine внизу, репликация наверху. С этим все плохо. В MySQL 5.6 и 5.7 эта проблема решена есть Group Binary Log Commit, и мастер теперь не отстает. Теперь это пытаются использовать для параллелизма репликации, чтобы на слэйве запросы из одной группы запустить параллельно. Тут я написал, что из этого нужно крутить:
![](Pasted%20image%2020240528090205.png)
## Параллельная репликация
Сценарий ([Estimating potential for MySQL 5.7 parallel replication](https://www.percona.com/blog/estimating-potential-for-mysql-5-7-parallel-replication/)):
- 1 мастер, 3 слейва
- первый реплицирует в 1 поток
- второй в 20 потоков
- третий в 100 потоков
- вставка в 25 различных таблиц внутри одной базы в 100 потоков
![](Pasted%20image%2020240606094633.png)
Полезные опции:
- sysvar_replica_parallel_workers - количество потоков
- sysvar_replica_parallel_type
- DATABASE - транзакции применяются параллельно, если они обновляют разные БД
- LOGICAL_CLOCK - транзакции применяются параллельно на реплике на основе timestamp
## Отставание реплики
- [Отставание реплики в БД](Отставание%20реплики%20в%20БД.md)
Диагностировать причину отставания реплики тяжело. Есть средство диагностики в MySQL, называется log медленных запросов. Вы можете его открыть, найти топ самых тяжелых запросов и исправить их. Но с репликацией это не работает. Нужно проводить статистический анализ считать статистику какие таблицы стали чаще использоваться. Вручную это сделать очень тяжело.
В MySQL 5.6 / 5.7 появилась SLAVE PERFORMANCE SCHEMA, на базе которой такую диагностику провести проще. Мы обычно открываем лог коммитов в puppet и смотрим, что же мы выкатили в то время, когда репликация начала отставать. Иногда даже это не помогает, приходится ходить по всем разработчикам и спрашивать, что они сделали, они ли сломали репликацию. Это грустно, но с этим приходится жить.
## Дополнительные материалы
- [Как устроена MySQL-репликация / Андрей Аксенов (Sphinx) - YouTube](https://www.youtube.com/watch?v=lHFaZkJk2O0)