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