====== Восстановление репликации master-slave MySQL ======
===== Действия на мастере =====
# На мастере запоминаем текущую позицию и имя файла:
mysql> show master status\G
*************************** 1. row ***************************
File: mysql-bin.045317
Position: 41951754
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
# На мастере выполняем дамп нужной БД и переливаем ее на Slave:
mysqldump -u root -p'$PASSWD' $DB_NAME --add-drop-table --insert-ignore --skip-lock-tables --single-transaction=TRUE | gzip -c | ssh $IP-SLAVE 'cat > /root/dump.sql.gz'
===== На слейве =====
# На слейве разворачиваем дамп в БД:
zcat /root/dump.sql.gz | mysql -u 'root' -p'$PAsswd' $DB_NAME
# На слейве меняем файл и позицию
mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.045317', MASTER_LOG_POS=41951754;
# И стартуем репликацию:
mysql> START SLAVE;
Если дамп сделан без проверки удаления и очистки таблиц, то можно очистить так:
mysqldump --add-drop-table --no-data $DB_NAME | grep ^DROP | sed -e 's/DROP TABLE IF EXISTS/TRUNCATE TABLE/g' | mysql $DB_NAME
Иногда следует обернуть TRUNCATE в SET FOREIGN_KEY_CHECKS=0; и SET FOREIGN_KEY_CHECKS=1;:
SET FOREIGN_KEY_CHECKS=0;
TRUNCATE TABLE `macro_estat_all_data`;
TRUNCATE TABLE `macro_estat_geo`;
TRUNCATE TABLE `macro_estat_items`;
TRUNCATE TABLE `macro_estat_nace_r2`;
TRUNCATE TABLE `macro_estat_s_adj`;
TRUNCATE TABLE `macro_estat_tasks`;
TRUNCATE TABLE `macro_estat_units`;
TRUNCATE TABLE `macro_tabs`;
TRUNCATE TABLE `sources`;
SET FOREIGN_KEY_CHECKS=1;
===== Для нестандартных случаев =====
Иногда случается так, что исходный сервер под нагрузкой, а целевой мертвый. При этом клиент прижимистый, а репликация ему ну **очень** нужна. Действуем размеренно и нежно, как с беременной кобылой.
#####
# На целевой машине слушаем порт 54321 через netcat
nc -l 54321 | gzip -d -c | mysql $DB_NAME -u root -p $PASSWD
#####
# На исходной машине начинаем передачу данных, ограничивая скорость потока в 1024 kBit/s.
mysqldump -u root -p$PASSWD $DB_NAME --insert-ignore --skip-lock-tables --single-transaction=TRUE | gzip | trickle -u 1024 nc $TARGET-IP 54321
Можно еще заморочиться и добавить шифрование в пайпы.
# На исходном сервере шифруем паролем 256256
/usr/bin/openssl enc -pbkdf2 -pass pass:256256 -e
# На целевом расшифровываем тем же паролем
/usr/bin/openssl enc -pbkdf2 -pass pass:256256 -d
Откупориваем напиток и следим за выполнением дампа
===== Скрипты для выполнения репликации =====
Как и любая рутинная работа, регулярное выполнение репликации надоедает. Разработчикам пополам на то, что внесение изменений в структуру БД вызывает ее расслоение и админы страдают и зеленеют от восторга. Пришлось написать пару скриптов для синхронизации БД и подъеме реплики, когда все уже развалилось
==== Скрипт для мастера ====
#/bin/bash
SLAVE="192.168.1.2 -p65522"
MysqlPass='passppaSS4word'
DbList="db1 db2 db3 db4 db5 db77"
#--
LOG=/tmp/dump-db.txt
log(){ echo "$(date '+%F %T') $@" >> $LOG; echo "$(date '+%F %T') $@";}
log "start>>>"
FILE=$(mysql -e "show master status\G" | grep File | awk '{print $2}' | xargs)
POS=$(mysql -e "show master status\G" | grep Position | awk '{print $2}' | xargs)
log "File $FILE, POSITION $POS"
for db in $DbList; do
log "start dump $db"
mysqldump -u root -p$MysqlPass --add-drop-table --insert-ignore --skip-lock-tables --single-transaction=TRUE -B $db 2>/dev/null |gzip -c |ssh $SLAVE "cat > /root/$db-sql.gz"
log "end dump $db"
done
log "start resore in $SLAVE"
ssh $SLAVE "/bin/bash /root/restore.sh $FILE $POS &"
log "end restore in $SLAVE"
log "-=end=-"
==== Скрипт для SLAVE ====
#!/bin/bash
MASTER_IP='192.168.1.1'
ARX_PATH='/root'
##--
if [ ! -z "$1" ]; then
FILE=$1
fi
if [ ! -z "$2" ]; then
POS=$2
fi
#--
LOG=/tmp/dump-db.txt
log(){ echo "$(date '+%F %T') $@" >> $LOG; echo "$(date '+%F %T') $@";}
log "start>>>"
DumpList=$(find $ARX_PATH -name '*-sql.gz' -type f |xargs)
for file in $DumpList; do
db=$(echo $file| sed "s|^/${ARX_PATH}/||;s|-sql.gz$||")
mysql -e "CREATE DATABASE IF NOT EXISTS $db;"
log "start restore $db from $file"
zcat $file | mysql -u root $db
log "end dump $db"
done
log "end dumps"
if [ ! -z "$POS" ] && [ ! -z "$FILE" ]; then
log "$FILE $POS"
log "Start Replica"
mysql -e "CHANGE MASTER TO MASTER_HOST='$MASTER_IP', MASTER_LOG_FILE='$FILE', MASTER_LOG_POS=$POS;"
mysql -e "START REPLICA;"
mysql -e "SHOW REPLICA STATUS\G"
fi
log "<<