Содержание

Восстановление репликации 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 "<<<end"