Какая вообще в природе бывает репликация (sync vs. async vs. semisync, master-master vs. master-slave), как оно устроено конкретно в MySQL, в каких версиях что добавили. Про binary/relay log, про SBR/RBR/mixed форматы, про глупости с позициями и про GTID, про то, как из-за всяких бед возникают дополнительные продукты типа Tungsten и Galera. Несколько занятных фактов и парочка фокусов, которые можно учинять конкретно с MySQL-репликацией.
Доклад вчистую про внутреннее устройство, по результатам должно появляться общее понимание того, как оно работает внутри и почему именно так. Конкретные SQL-операторы подробно рассматривать НЕ будем, эти скучные мелочи необходимо будет затем самостоятельно смотреть в документации (или не смотреть).
2. О чем доклад
• Краткий общий обзор
• “А как оно устроено внутри”
– Как бывает в целом
– Как сделано в MySQL
• Если совсем не знаете, оставайтесь
• Если хоть раз настраивали или даже
чинили, возможно, лучше убежать!!!
3. Чего щаз НЕ будет
• Мастер: [mysqld], log-bin=binlog, server-id=1,
остановить запись, SHOW MASTER STATUS
• Слейв: [mysqld], server-id=2
CHANGE MASTER TO …_HOST/USER/PASS=…,
MASTER_LOG_FILE=‘binlog.000001’,
MASTER_LOG_POS=1234;
START SLAVE;
• Обучалки replication 101 и в интернетах есть
(Хотя, технически, там все есть: исходники!)
6. Про масштабирование
• Что дает репликация?
• Дает N копий одной БД
– 1 ведущия копия, мастер
– N ведомых реплик, слейвы
• Дает HA (high availability)
• Дает масштабирование reads
• НЕ дает масштабирования writes!
– Shard, shard, shard
7. Про синхронизацию
• Sync = local + remote commit
– Данные доступны везде
• Async = local commit
– Данные доступны только локально
• Semi = local commit + remote ack
– Данные доступны только локально,
но уже скопированы везде
8. Про уровень
• Logical = копируем “записи”
– Строго внутри БД
• Physical = копируем “файлы”
– Можно внутри, можно вне БД
– DRBD, ZFS, …
9. Про модель
• Кто ответственный за рассылку
изменений с мастера?
• Pull = слейв качает, мастеру пофиг
• Push = мастер сует, слейву пофиг
• Push если и бывает, то рееедко
10. Про мастеров
• M-S, 1 ведущая + N ведомых
• M-M, N ведущих + они же ведомые
– Упс, конфликты, сверка часов, …
– Упс, не обязано помочь write bandwidth!
– Зато cross-DC disaster recovery, говорят!!!
• M-S + routing = писать “куда угодно”
• Читать и так откуда угодно, всегда
11. И еще про logical format
• Можно передавать сами запросы
– UPDATE table SET x=123 WHERE id=456
– SBR, statement based replication
• Можно передавать измененные строчки
– {“id”:456, “x”:123} (есс-но в бинарном формате)
– RBR, row based replication
• И так и эдак плохо – но можно смешивать,
mixed
14. Что делает мастер
• Как обычно, обрабатывает writes
• Вдобавок, из-за репликации
– Еще надо писать binlogs
– Еще надо уметь рассылать их по сетке
• NB, архитектура бьет спина!
– MySQL binlog != InnoDB WAL !=
MyMegaEngine oplog != …
– Двойная запись и все такое
15. Что делает слейв
• Как обычно, обрабатывает reads
– Писать туда ОЙ НЕ НАДО
• Slave I/O thread, качаем binlogs
• Slave SQL thread(s), играем binlogs
• Отслеживаем позиции
– либо master/relay log info
– либо GTID
17. Самурай без меча...
• INSERT INTO test VALUES (123,’hello’)
• Приложение-писатель
=> таблица на мастере mysqld
=> приложение-читатель
18. ...подобен самураю с мечом
• INSERT INTO test VALUES (123,’hello’)
• Приложение-писатель
=> таблица на мастере mysqld
=> binary log на мастере
=> relay log на слейве
=> таблица на слейве mysqld
=> приложение-читатель
19. Ок, что там в binary log?
• Зависит от настроек SBR/RBR/mixed
• Представь себя базой данных!!!
• UPDATE users SET x=123 WHERE id=456
– Плюс-минус пофигу
• UPDATE users SET bonus=bonus+100
– Запрос = 32 байта, пользователей = ууу, ааа
– Надо писать текст запроса, и вот мы изобрели
SBR, statement based replication
20. Ок, что там в binary log?
• UPDATE users SET disabled=1 WHERE
last_login < UNIX_TIMESTAMP(NOW())-
100*86400
– Для краткости надо бы сам запрос, но…
21.
22. Ок, что там в binary log?
• UPDATE users SET disabled=1 WHERE
last_login < UNIX_TIMESTAMP(NOW())-
100*86400
– Время никогда не синхронно!
– Опа, реплика разошлась с мастером!
– Опа, надо бы строчки, а не запрос
– И вот мы изобрели RBR, row based replication
• А ещё бывает uuid(), found_rows(), rand(),
разные UDF, триггер на апдейт
auto_increment поля, …
23. Борода под/над одеялом!
• SBR хорошо, меньше данных
• SBR плохо, недетерминизм (rand,
now, итп), перевычисление сложного
• RBR хорошо, детерминизм и можно
реплицировать уааабще всё
• RBR плохо, куча данных в логе, никак
не отличить границы statement
• Есть вариант смешивать
24. Mixed binlog format
• Mixed = SBR, но иногда RBR
• Олимпиард условий, см.доку
– UUID(), FOUND_ROWS(), USER(), sysvar
reference, LOAD_FILE(), autoincrement +
trigger/stored function, UDF call, …
• В целом, пытается как лучше, а…
• Дефолтом стояло чуток в 5.1 – и все
25. Как, кстати, посмотреть?
• RBR, mysqlbinlog –v:
# at 218 #080828 15:03:08 server id 1 end_log_pos 258
Write_rows: table id 17 flags: STMT_END_F
BINLOG '
fAS3SBMBAAAALAAAANoAAAAAABEAAAAAAAAABHRlc3QAA
XQAAwMPCgIUAAQ=
fAS3SBcBAAAAKAAAAAIBAAAQABEAAAAAAAEAA//8AQAAAA
VhcHBsZQ== '/*!*/;
### INSERT INTO test.t
### SET
### @1=1
### @2='apple‘
### @3=NULL
26. Ок, что дальше?
• INSERT INTO test VALUES (123,’hello’)
• Приложение-писатель
=> таблица на мастере mysqld
=> binary log на мастере
=> relay log на слейве
=> таблица на слейве mysqld
=> приложение-читатель
27. Есть ли жизнь на слейве?
• Спецтред, тащит binary log по сети
• Пишет в relay log, локальную копию
• Другое имя файла, позиции, итд итп
• По 5.5 включительно,
– слейв 1-поточный
– txn_id = {master binlog fname, pos}
28.
29. Есть ли жизнь на слейве?
• По 5.5 включительно,
– слейв 1-поточный
– txn_id = {master binlog fname, pos}
• 5.6.5, началась борьба!
– слейвы “многопоточные”, per database
– txn_id = GTID, но надо явно включить!
– gtid_mode=ON
30. Есть ли жизнь на слейве?
• 5.6.5, началась борьба!
– слейвы “многопоточные”, per database
– txn_id = GTID
• 5.7.2, борьба продолжается!
– поистине многопоточные слейвы
– slave_parallel_workers=N
– slave_parallel_type={ogical_clock
– binlog_group_commit_{count | delay}
31. Есть ли жизнь на слейве?
• 5.7.7, борьба ваще продолжается!
– binlog_format = ROW
– binlog_row_image = FULL
32. Внезапно, снова binlog
• binlog_row_image =
– Full = полные before + after копии!!!
– Noblob = полные, кроме ненужных blob
– Minimal = changed + ID columns
33.
34. Итого, про версии MySQL
• Чем свежее, тем бодрее
– 5.7 + gtid + groupcommit + mts = FTW!
– 5.6 + gtid = ну хоть так!
• Но: дефолты, дефолты, дефолты...
– По умолчанию всякое отключено
– Или включено full row (*)
• Не, ну, э, ну, э, ну может теперь ок?!…
• Также: минорные версии важны!
35. Итого, про репликацию
• В целом бывает – вот такая
• В MySQL устроена – вот так
• В принципе – не так все сложно
• Однако – надо представлять себе
ключевые слова binlog, relay log,
SBR/RBR, GTID, MTS, group commit, …
• Вот, попробовали попредставлять!
38. Всякие проблемы
• Начальный слейв (см. --master-data)
• У слейва протух лог, слетела позиция итп
• Слейв лагает и никак не может догнать
• Мастер забивает логами весь диск
• Ручные “перевыборы” мастера
• Слейвы с GTID бывают crash unsafe
• Ошибочные слейв транзакции с GTID
• …
39. Всякие фокусы
• Мастер A => мастер B => мастер C … => A!
• Catch-all слейв (multi source, 5.7.6+)
• Репликация логическая, возможен креатив!
– Фильтрация через {binlog|replicate}_{do|ignore}
– Подмена storage engine (innodb => myisam ради
fts, => archive для бэкапа, итд итп)
– Подмена схемы на слейве (не грузить же мастер)
– Апгрейд репликацией
– ….
40. Всякие ключевые слова
• server-id, SHOW MASTER/SLAVE STATUS, SHOW SLAVE
HOSTS, CHANGE MASTER TO …, START/STOP SLAVE, …
• SHOW BINARY LOGS, SHOW BINLOG EVENTS, …
• Tungsten Replicator, Galera, MySQL…
• {binlog|replicate}_{do|ignore}_db, …
• MySQL Replication Listener
• log_slave_updates, slave_checkpoint_{group|period}
• {master|relay_log}_info_repository={file|table}
• gtid_{executed|purged}