MySQL gtid репликация docker

Мастер

Создаейте каталог /srv/docker/mysql

docker-compose.yml

version: '3.8'

services:
  mysql:
    image: mysql:5
    restart: unless-stopped
    container_name: mysql
    user: mysql:mysql
    ports:
      - 3306:3306
    volumes:
# Сохраняем данные вне контейнера, создайте каталог /var/lib/mydata/mysql 
# и дайте на него права на пользователя с ID 999.
      - /var/lib/mydata/mysql:/var/lib/mysql
# Это наш конфиг
      - /srv/docker/mysql/my.cnf:/etc/mysql/mysql.conf.d/my.cnf
    environment:
      #Не меняем эти параметры
      MYSQL_ROOT_PASSWORD: root-password

my.cnf

[mysqld]
# Уникальный идентификатор сервера
server-id = 1
# Тут можно указать путь и название файла, в данном случаем бинлог будет в /var/lib/mysql
log-bin = mysql-bin
# Сколько дней хранить бинлог
expire-logs-days = 14
# Максимальный размер файла
max-binlog-size  = 500M
# Формат бинлога. MIXED я думаю оптимально.
binlog-format = MIXED
# Включаем gtid
gtid-mode = on
# Запрещает все, что может поломать транзакции. 
enforce-gtid-consistency = true
# Указывает подчиненному серверу, чтобы тот вел записи об обновлениях, происходящих на подчиненном сервере, в двоичном журнале. 
# По умолчанию эта опция выключена. Ее следует включить, если требуется организовать подчиненные серверы в гирляндную цепь.
# log-slave-updates = true

Запускаем/перезапускаем mysql

Создаем пользователя для репликации.

# docker exec -it mysql mysql -u root -p
sql> GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY 'password';

Делаем дамп базы

docker exec -i mysql sh -c 'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --all-databases --single-transaction --flush-logs --triggers --routines --events' > master.sql

Слейв

Делаем все то же что на мастере, но чуть чуть меняем конфиг

[mysqld]
# Тут меняем ID
server-id = 2
# Тут можно указать путь и название файла, в данном случаем бинлог будет в /var/lib/mysql
# log-bin = mysql-bin
# Указываем имя файлов relay лога. Если нужно создать гирляндовую сеть
# relay-log=relay-bin
# Сколько дней хранить бинлог
# expire-logs-days = 15
# Максимальный размер файла
# max-binlog-size  = 500M
# Формат бинлога. MIXED я думаю оптимально.
# binlog-format = MIXED
# Включаем gtid
gtid-mode = on
# Запрещает все, что может поломать транзакции. 
enforce-gtid-consistency = true
# Указывает подчиненному серверу, чтобы тот вел записи об обновлениях, происходящих на подчиненном сервере, в двоичном журнале. 
# По умолчанию эта опция выключена. Ее следует включить, если требуется организовать подчиненные серверы в гирляндную цепь.
# log-slave-updates = true

Если нужно сбросить старый слейв то вводим команды:

# docker exec -it mysql-slave mysql -u root -p
sql> stop slave;
sql> reset slave;

Импорт базы

docker exec -i mysql-slave sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" ' < master.sql

Иногда бывает ошибка при сохранении позиции на слейве

ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

В таком случае вводим комнаду.

reset master;

И запускаем реплику повторно.

Далее настраиваем репликацию. 10.10.0.1 - адрес мастера.

# docker exec -it mysql-slave mysql -u root -p
sql> CHANGE MASTER TO MASTER_HOST='10.10.0.1', MASTER_PORT=3306, MASTER_USER='slave_user', MASTER_PASSWORD='password', MASTER_AUTO_POSITION=1;
sql> start slave;

Ну и смотрим результат

show slave status \G;

Если нужно на мастере посмотреть текущую позицию то набираем

SHOW MASTER STATUS;

Правки для mariadb

В mysql gtid вставляется автоматически в файл дампа, но в mariadb такого, как я знаю не происходит. Поэтому нужно перед дампом сделать следующее. И записать значние gtid_current_pos

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SET GLOBAL read_only = ON; 
mysql> SELECT @@GLOBAL.gtid_current_pos;

Далее делаем дамп. И после того, как оно будет создан, можно разрешить запись в базу.

mysql> SET GLOBAL read_only = OFF;
mysql> UNLOCK TABLES; 

Далее уже на слейве заменяем 0-155-4480752978 на ранее сохраненный gtid_current_pos

mysql> SET GLOBAL gtid_slave_pos = '0-155-4480752978';
mysql> CHANGE MASTER TO master_host="10.10.0.1", master_user="root", MASTER_PASSWORD='password',  master_use_gtid=current_pos;

Полезные команды

Что бы сразу залить дамп на слейв можно использовать вот такую команду на мастере. Где 10.10.0.2 адрес слейва.

mysqldump --all-databases --single-transaction --flush-logs --triggers --routines --events --compress -u root -ppassword | mysql --host=10.10.0.2 --port=3306 -u root -ppassword

[ Править ]

@kiranananda