Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save joshuasign/97b8f515ef28fdabf8fd79643509104c to your computer and use it in GitHub Desktop.
Save joshuasign/97b8f515ef28fdabf8fd79643509104c to your computer and use it in GitHub Desktop.
MySQL_REBUILD_LIVE_SLAVE_from_MASTER
#!/usr/bin/env bash
# Name: MySQL_HOTREBUILD_SLAVE_from_MASTER.sh by Joshua_sign
# original version was MySQL_REBUILD_LIVE_SLAVE_from_MASTER by Matthew Crenshaw
#
# Purpose: Rebuilds live for one or all Databases of a SLAVE replication server based on a good running MASTER server
# This rebuilt action is done without stopping the MASTER MySQL server BUT by locking the MASTER server tables
# during the backup of master databases with the F method (minimal duration possible)
# or during the whole transfert with the P method.
# Note that a main difference with the original script of Matthew Crenshaw, this version is used for a symetric MASTER/SLAVE.
# In other words, the SLAVE can became a MASTER if the MASTER go down, and MASTER can became SLAVE if needed.
# So we set MASTER/SLAVE informations in both servers.
#
# Syntax: MySQL_HOTREBUILD_SLAVE_from_MASTER.sh Master:Port Slave:Port {F|P} [this_dbname_only]
# eg. MySQL_HOTREBUILD_SLAVE_from_MASTER.sh db1:3306 www1:3306 P myDatabase
# {F|P} - Dump method F) Uses a full temporary dump file method P) Uses the pipe method
# Note: In some situation where the databases are very big (GB) the Pipe (P) method might not work well
# In these case it is recommended to use the File(F) method
#
# Changes: 05 Dec 2008 First implementation of script
# 10 Oct 2013 Added the File(F) transfer method, added --skip-lock-tables to the dump command, added the manual entry of root PW
# 05 Jan 2017 Modifications about the main process : this rebuild cannot be made without locking tables on Master server during the backup
# removes --routines and --triggers because my mysql does not support them
# change the DUMPFILE emplacement for security reasons (because only root should use this script)
# replace nmap in testhost function by a mysql test because nmap is not needed on Mysql Servers (my server cant get nmap)
# remove usage of ssh and rsync
# rebuild only one database is now possible with the 4th parameter (optional)
# 03 Mar 2017 add default values for replication user and password, master / slave servers ip:ports, mode, database name
# add description for error 1201
# 09 Oct 2018 remove --lock-all-tables because MariaDB catch an error : "mysqldump: You can't use --single-transaction and --lock-all-tables at the same time."
#
# Notes
# 1: Joshua_sign : P method has been successfully tested on 1Gb lan with 2 databases sized at 7GB each (more than 350 tables each in InnoDB)
# But, if you need the faster method, use F because the master server is only freezed during export to dumpfile
# With F method we must freeze master during the whole transfert time.
#
# Todo: Change params setting because default params are avaiable and multiple databases can be sets
# Detect the "ERROR 1201" automatically, and/or add ssh access to delete them by this script
#
# Known Errors:
# "ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log"
# I got this error sometimes on 64Bits server with debian 6.0.5 and mysql 5.1.63-0+squeeze1-log
# This error may happens on starting slave when the RESET SLAVE command didn't delete files into /var/lib/mysql/mysqld-relay-bin.*
# 'reset slave' should normaly cleanup directory /var/lib/mysql/, but sometimes it does not
# So to fix this error just perform a STOP SLAVE; and RESET SLAVE; on the server (master or SLAVE, deppending where the error occurs)
# You will see if files like /var/lib/mysql/mysqld-relay-bin.* are deleted automatically.
# If they are not, you can do it with rm -f /var/lib/mysql/mysqld-relay-bin.*
# Then you can try to START SLAVE; or launch this script again, and everythings should be ok.
#
#-----------------------------------------------------------------------------------
#
# Standard output exemple :
# MYBDD1: 7GB database, more than 400 tables
# MYBDD2: empty db just for test.
#
# root@myserver:~ $ ./MySQL_HOTREBUILD_SLAVE_from_MASTER.sh 192.168.2.4:3306 192.168.2.5:3309 F
# Please enter the MySQL root password:
# Please enter the MySQL replication user name:
# Please enter the MySQL replication user password:
# [09/01/2017-11:05:35] Ready to work! (starting sync in 10 seconds, press CTRL+C to abord)
# [09/01/2017-11:05:45] Lock all tables on Master....
# [09/01/2017-11:05:50] Master is now freezed
# [09/01/2017-11:05:50] Flush and reset slave...
# [09/01/2017-11:05:50] Flush and reset master...
# [09/01/2017-11:05:50] Dumping from master 192.168.2.4:3306 into file /root/mydump.sql
# [09/01/2017-11:05:50] Databases : MYBDD1 MYBDD2
# [09/01/2017-11:07:52] UNLOCK all tables on Master....
# [09/01/2017-11:07:52] Killing SLEEP on pid 19017...
# [09/01/2017-11:07:52] Master is now operational
# [09/01/2017-11:07:52] Update master information on Slave...
# [09/01/2017-11:07:52] Import dumpfile /root/mydump.sql into slave 192.168.2.5:3309 ... (this may take a while)
# [09/01/2017-11:19:34] Update master information on Master...
# [09/01/2017-11:19:34] Starting slave replication on Slave 192.168.2.5....
# *************************** 1. row ***************************
# Slave_IO_State: Waiting for master to send event
# Master_Host: 192.168.2.4
# Master_User: replication
# Master_Port: 3306
# Connect_Retry: 60
# Master_Log_File: mysql-bin.000002
# Read_Master_Log_Pos: 300828
# Relay_Log_File: mysqld-relay-bin.000002
# Relay_Log_Pos: 300973
# Relay_Master_Log_File: mysql-bin.000002
# Slave_IO_Running: Yes
# Slave_SQL_Running: Yes
# Replicate_Do_DB:
# Replicate_Ignore_DB:
# Replicate_Do_Table:
# Replicate_Ignore_Table:
# Replicate_Wild_Do_Table:
# Replicate_Wild_Ignore_Table:
# Last_Errno: 0
# Last_Error:
# Skip_Counter: 0
# Exec_Master_Log_Pos: 300828
# Relay_Log_Space: 301129
# Until_Condition: None
# Until_Log_File:
# Until_Log_Pos: 0
# Master_SSL_Allowed: No
# Master_SSL_CA_File:
# Master_SSL_CA_Path:
# Master_SSL_Cert:
# Master_SSL_Cipher:
# Master_SSL_Key:
# Seconds_Behind_Master: 0
# Master_SSL_Verify_Server_Cert: No
# Last_IO_Errno: 0
# Last_IO_Error:
# Last_SQL_Errno: 0
# Last_SQL_Error:
# [09/01/2017-11:19:37] Starting slave replication on Master 192.168.2.4....
# *************************** 1. row ***************************
# Slave_IO_State: Waiting for master to send event
# Master_Host: 192.168.2.5
# Master_User: replication
# Master_Port: 3309
# Connect_Retry: 60
# Master_Log_File: mysql-bin.000007
# Read_Master_Log_Pos: 295556762
# Relay_Log_File: mysqld-relay-bin.000002
# Relay_Log_Pos: 251
# Relay_Master_Log_File: mysql-bin.000007
# Slave_IO_Running: Yes
# Slave_SQL_Running: Yes
# Replicate_Do_DB:
# Replicate_Ignore_DB:
# Replicate_Do_Table:
# Replicate_Ignore_Table:
# Replicate_Wild_Do_Table:
# Replicate_Wild_Ignore_Table:
# Last_Errno: 0
# Last_Error:
# Skip_Counter: 0
# Exec_Master_Log_Pos: 295556762
# Relay_Log_Space: 407
# Until_Condition: None
# Until_Log_File:
# Until_Log_Pos: 0
# Master_SSL_Allowed: No
# Master_SSL_CA_File:
# Master_SSL_CA_Path:
# Master_SSL_Cert:
# Master_SSL_Cipher:
# Master_SSL_Key:
# Seconds_Behind_Master: 0
# Master_SSL_Verify_Server_Cert: No
# Last_IO_Errno: 0
# Last_IO_Error:
# Last_SQL_Errno: 0
# Last_SQL_Error:
# [09/01/2017-11:19:40] End of jobs.
#
#-----------------------------------------------------------------------------------
#
# Defaults Variables
#
# Default replication user and password :
defRepUsr="replication"
defRepPwd="replication_user_password"
#
# Default Master server ip:port
defMaster="192.168.1.4:3306"
#
# Default Slave server ip:port
defSlave="192.168.1.5:3306"
#
# Default mode of sync
# mode : F (file) or P (pipe)
defMode="F"
#
# Default database name
defDatabase="MyDATABASE"
#
# Enable verbose mode : for debugging purpose
verbose=1
#
# Must we show password on verbose mode : only for verbose=1
# (passwords can be shown on verbose mode only)
showPasswords=0
#
# temporary file for F mode :
DUMPFILE="/root/mydump.sql"
#
# Resync the databases except the following Databases
# Joshua_sign : header "Database" must not be used
EXCEPTIONS="information_schema mysql test Database"
#
#-----------------------------------------------------------------------------------
#
# Functions
#
# Syntax: testhost addr port pwd
# Returns: hostOK=1
testhost () {
mySrvTest=$(echo quit | mysql -u root -p$3 --port $2 -h $1)
if [ $? -eq 0 ];then
hostOK=1
else
hostOK=0
fi
};
fn_echo(){
echo -e "[`date '+%d/%m/%Y-%H:%M:%S'`] $1"
}
# standard help
usage () {
echo ""
echo "ERROR: Somethig is wrong with the given arguments"
echo "Syntax: $0 Master:Port Slave:port {F|P} [this_dbname_only]"
echo " eg. $0 master1:3306 slave1:3306 P"
echo ""
exit 1
}
# Get the mysql replication user name
if [ -z ${defRepUsr+x} ]; then varStr=""; else varStr=" (leave empty for default)"; fi
read -s -p "Please enter the MySQL replication user name$varStr: " replication_user
echo ""
if [ "$replication_user" == "" ];then
replication_user="${replication_user:-$defRepUsr}"
fi
if [ -z ${defRepUsr+x} -a "$replication_user" == "" ];then
echo "ERROR: The replication user name cannont be empty"
exit 1
fi
# Get the mysql replication user password
if [ -z ${defRepPwd+x} ]; then varStr=""; else varStr=" (leave empty for default)"; fi
read -s -p "Please enter the MySQL replication user password$varStr: " replication_pwd
echo ""
if [ "$replication_pwd" == "" ];then
replication_pwd="${replication_pwd:-$defRepPwd}"
fi
if [ -z ${defRepPwd+x} -a "$replication_pwd" == "" ];then
echo "ERROR: The replication user password cannont be empty"
exit 2
fi
#- Check the hosts info validity
if [ -z ${defMaster+x} ]; then master=$(echo $1 | grep ':'); else master=$(echo $defMaster | grep ':'); fi
if [ "$master" == "" ]; then
echo "ERROR: The 2nd parameter(master) must be the combination 'host:port'"
exit 3
fi
#
if [ -z ${defSlave+x} ]; then slave=$(echo $2 | grep ':'); else slave=$(echo $defSlave | grep ':'); fi
if [ "$slave" == "" ]; then
echo "ERROR: The third parameter must be the combination 'host:port'"
exit 4
fi
#
if [ -z ${defMode+x} ]; then method=$3; else method=$defMode; fi
if [ -z ${defDatabase+x} ]; then databases=$4; else databases=$defDatabase; fi
if [ "$master" == "" -o "$slave" == "" -o "$method" == "" ];then
echo "Wrongs parameters : mode $method - master : $master - slave : $slave"
exit 1
fi
# Get the mysql root password
read -s -p "Please enter the MySQL root password: " rootpw
echo ""
if [ "$rootpw" == "" ];then
echo "ERROR: The ROOT password cannont be empty"
exit 2
fi
#
# Check the hosts connectivity of master host
Mhost=$(echo $master | cut -d: -f1)
Mport=$(echo $master | cut -d: -f2)
#
testhost $Mhost $Mport $rootpw
if [ $hostOK = "0" ]; then
echo "ERROR: The master $Mhost:$Mport does not respond for user root with the given password"
exit 5
fi
#
# Check the hosts connectivity of slave host
#
Shost=$(echo $slave | cut -d: -f1)
Sport=$(echo $slave | cut -d: -f2)
#
testhost $Shost $Sport $rootpw
if [ $hostOK = "0" ]; then
echo "ERROR: The slave $Shost:$Sport does not respond for user root with the given password"
exit 6
fi
MASTER="--host=$Mhost --port=$Mport --user=root --password=$rootpw"
SLAVE="--host=$Shost --port=$Sport --user=root --password=$rootpw"
MASTERNOPW="--host=$Mhost --port=$Mport --user=root --password=xxxxxxxxxxx"
SLAVENOPW="--host=$Shost --port=$Sport --user=root --password=xxxxxxxxxxx"
# if no database given on command line, get all databases (without exceptions ones)
if [ "$databases" == "" ]; then
for DB in $(echo "show databases;" | mysql $MASTER) ; do
# Only delete/add the databases that are not in the Exceptions list
if ! (echo $EXCEPTIONS | grep -q $DB); then
# here I was deleting the databases one by one before recreating them in slave
# I replaced this by the option --add-drop-database in mysqldump
#echo "Deleting database $DB on Slave $Shost:$Sport"
#echo "DROP DATABASE $DB;" | mysql -h $Shost --port=$Sport -u root --password=$rootpw
# Corrected. Thanks to Dorian Kavaja
if [ "$databases" == "" ]; then
databases=$DB
else
databases="$databases $DB"
fi
fi
done
fi
if [ "$databases" == "" ]; then
echo "ERROR: No database found"
exit 7
fi
#
# NOW All the tests are OK : the good job start now
#
if [ $verbose -eq 1 ];then
fn_echo "DEBUG MODE - Ready to work! (starting sync in 30 seconds, press CTRL+C to abord)"
fn_echo "DEBUG - Master Host:Port : $Mhost:$Mport"
fn_echo "DEBUG - Slave Host:Port : $Shost:$Sport"
fn_echo "DEBUG - Databases : $databases"
fn_echo "DEBUG - Sync Method : $method"
if [ $showPasswords -eq 1 ];then
fn_echo "DEBUG - Replication user/pwd : [$replication_user/$replication_pwd]"
else
fn_echo "DEBUG - Replication user/pwd : [$replication_user/xxxxxxxxxxxx]"
fi
sleep 30
else
fn_echo "Ready to work! (starting sync in 10 seconds, press CTRL+C to abord)"
sleep 10
fi
# added by Joshua_sign
# Step 1 : lock all tables, and keep connection open to avoid auto unlock on disconnect
# useless since mysqldump do the job, but we keep it to ensure locking
fn_echo "Lock all tables on Master...."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on Master $Mhost:$Mport : \"FLUSH TABLES WITH READ LOCK;SELECT SLEEP(3600);\""; fi
echo "FLUSH TABLES WITH READ LOCK;SELECT SLEEP(3600);" | mysql $MASTER &> /dev/null & sleep 5
fn_echo "Master is now freezed"
# Step 2 : Stop and reset the slave and the master
fn_echo "Flush and reset slave..."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on Slave $Shost:$Sport : \"FLUSH LOGS; RESET QUERY CACHE; RESET MASTER; STOP SLAVE; RESET SLAVE;\""; fi
echo "FLUSH LOGS; RESET QUERY CACHE; RESET MASTER; STOP SLAVE; RESET SLAVE;" | mysql $SLAVE
# The following lines is thanks to Dorian Kavaja
# because sometimes the log file on the master was changed before the dump was finished
fn_echo "Flush and reset master..."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on Master $Mhost:$Mport : \"FLUSH LOGS; RESET QUERY CACHE; RESET MASTER; STOP SLAVE; RESET SLAVE;\""; fi
echo "FLUSH LOGS; RESET QUERY CACHE; RESET MASTER; STOP SLAVE; RESET SLAVE;" | mysql $MASTER
# Step 3
# Now do the transfer
# Added “–routines –triggers” to the mysqldump command, so triggers and functions were included in the dump.
# Thanks to Dorian Kavaja
# Joshua_sign : Remove "--routines" and "-–triggers" because my server does not support them : 5.1.63-0+squeeze1-log - (Debian)
# Master-data to 1 (default) should be the best and easier way (https://dev.mysql.com/doc/refman/5.5/en/mysqldump.html#option_mysqldump_master-data) but it does not work.
# Remove --single-transaction and --skip-lock-tables because resyncing without locking is just a dream on production server with many connections
# Added --lock-all-tables
# Remove --lock-all-tables because MariaDB catch an error : "mysqldump: You can't use --single-transaction and --lock-all-tables at the same time."
case $method in
P) # Transfer all databases from master to slave directly using a pipe(P)
fn_echo "Transfering from master $Mhost:$Mport into slave $Shost:$Sport directly"
fn_echo "Databases : $databases"
if [ $verbose -eq 1 ]; then
if [ $showPasswords -eq 1 ];then
fn_echo "DEBUG - Performing : \"mysqldump $MASTER --flush-logs --add-drop-database --delete-master-logs --hex-blob --databases $databases | mysql $SLAVE\"";
else
fn_echo "DEBUG - Performing : \"mysqldump $MASTERNOPW --flush-logs --add-drop-database --delete-master-logs --hex-blob --databases $databases | mysql $SLAVENOPW\"";
fi
fi
mysqldump $MASTER --flush-logs --add-drop-database --delete-master-logs --hex-blob --databases $databases | mysql $SLAVE
# Find out the master binlog file name and position
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Catching the master_log_file and master_log_position on master $Mhost:$Mport by : \"SHOW MASTER STATUS\G;\""; fi
masterlogfile_forslave=$(echo "SHOW MASTER STATUS\G;" | mysql $MASTER | grep "File:" | cut -d: -f2 | cut -d" " -f2)
masterlogpos_forslave=$(echo "SHOW MASTER STATUS\G;" | mysql $MASTER | grep "Position:" | cut -d: -f2 | cut -d" " -f2)
if [ $verbose -eq 1 ];then
fn_echo "DEBUG - Catched 'master_log_file' on master $Mhost:$Mport : $masterlogfile_forslave"
fn_echo "DEBUG - Catched 'master_log_position' on master $Mhost:$Mport : $masterlogpos_forslave"
fi
fn_echo "UNLOCK all tables on Master...."
# kill the sleep
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Recovering sleep process PID on master $Mhost:$Mport"; fi
pid=$(echo "SHOW PROCESSLIST" | mysql $MASTER | grep 'SLEEP(3600)' | cut -d" " -f1)
if [ "$pid" != "" ]; then
fn_echo "Killing SLEEP on pid $pid..."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"KILL CONNECTION $pid;\""; fi
echo "KILL CONNECTION $pid;" | mysql $MASTER
fi
# this is useless because of killing sleep kill the connection that lock tables
# and behavior is that "FLUSH TABLES WITH READ LOCK" is only true while connection doing it is active
# but its better to do it, just in case... otherwise if behavior dont work, master stay freezed 1 hour
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"UNLOCK TABLES;\""; fi;
echo "UNLOCK TABLES;" | mysql $MASTER
fn_echo "Master is now operational"
fn_echo "Update master information on Slave..."
if [ $verbose -eq 1 ];then
if [ $showPasswords -eq 1 ];then
fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"CHANGE MASTER TO MASTER_HOST='$Mhost', MASTER_USER='$replication_user', MASTER_PASSWORD='$replication_pwd', MASTER_LOG_FILE='$masterlogfile_forslave', MASTER_LOG_POS=$masterlogpos_forslave;\"";
else
fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"CHANGE MASTER TO MASTER_HOST='$Mhost', MASTER_USER='$replication_user', MASTER_PASSWORD='xxxxxxxxxx', MASTER_LOG_FILE='$masterlogfile_forslave', MASTER_LOG_POS=$masterlogpos_forslave;\"";
fi
fi
echo "CHANGE MASTER TO MASTER_HOST='$Mhost', MASTER_USER='$replication_user', MASTER_PASSWORD='$replication_pwd', MASTER_LOG_FILE='$masterlogfile_forslave', MASTER_LOG_POS=$masterlogpos_forslave;" | mysql $SLAVE
;;
#
F) # Transfer the databases using a dump file
fn_echo "Dumping from master $Mhost:$Mport into file $DUMPFILE"
fn_echo "Databases : $databases"
if [ $verbose -eq 1 ];then
if [ $showPasswords -eq 1 ];then
fn_echo "DEBUG - Performing : \"mysqldump $MASTER --flush-logs --add-drop-database --delete-master-logs --hex-blob --databases $databases > $DUMPFILE\"";
else
fn_echo "DEBUG - Performing : \"mysqldump $MASTERNOPW --flush-logs --add-drop-database --delete-master-logs --hex-blob --databases $databases > $DUMPFILE\"";
fi
fi
mysqldump $MASTER --flush-logs --add-drop-database --delete-master-logs --hex-blob --databases $databases > $DUMPFILE
# Find out the master binlog file name and position
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Catching the master_log_file and master_log_position on master $Mhost:$Mport by : \"SHOW MASTER STATUS\G;\""; fi
masterlogfile_forslave=$(echo "SHOW MASTER STATUS\G;" | mysql $MASTER | grep "File:" | cut -d: -f2 | cut -d" " -f2)
masterlogpos_forslave=$(echo "SHOW MASTER STATUS\G;" | mysql $MASTER | grep "Position:" | cut -d: -f2 | cut -d" " -f2)
if [ $verbose -eq 1 ];then
fn_echo "DEBUG - Catched 'master_log_file' on master $Mhost:$Mport : $masterlogfile_forslave"
fn_echo "DEBUG - Catched 'master_log_position' on master $Mhost:$Mport : $masterlogpos_forslave"
fi
fn_echo "UNLOCK all tables on Master...."
# kill the sleep
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Recovering sleep process PID on master $Mhost:$Mport"; fi
pid=$(echo "SHOW PROCESSLIST" | mysql $MASTER | grep 'SLEEP(3600)' | cut -d$'\t' -f1)
if [ "$pid" != "" ]; then
fn_echo "Killing SLEEP on pid $pid..."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"KILL CONNECTION $pid;\""; fi
echo "KILL CONNECTION $pid;" | mysql $MASTER
fi
# this is useless because of killing sleep kill the connection that lock tables
# and behavior is that "FLUSH TABLES WITH READ LOCK" is only true while connection doing it is active
# but its better to do it, just in case... otherwise if behavior dont work, master stay freezed 1 hour
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"UNLOCK TABLES;\""; fi;
echo "UNLOCK TABLES;" | mysql $MASTER
fn_echo "Master is now operational"
#
fn_echo "Update master information on Slave..."
if [ $verbose -eq 1 ];then
if [ $showPasswords -eq 1 ];then
fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"CHANGE MASTER TO MASTER_HOST='$Mhost', MASTER_USER='$replication_user', MASTER_PASSWORD='$replication_pwd', MASTER_LOG_FILE='$masterlogfile_forslave', MASTER_LOG_POS=$masterlogpos_forslave;\"";
else
fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"CHANGE MASTER TO MASTER_HOST='$Mhost', MASTER_USER='$replication_user', MASTER_PASSWORD='xxxxxxxxxx', MASTER_LOG_FILE='$masterlogfile_forslave', MASTER_LOG_POS=$masterlogpos_forslave;\"";
fi
fi
echo "CHANGE MASTER TO MASTER_HOST='$Mhost', MASTER_USER='$replication_user', MASTER_PASSWORD='$replication_pwd', MASTER_LOG_FILE='$masterlogfile_forslave', MASTER_LOG_POS=$masterlogpos_forslave;" | mysql $SLAVE
# modified by Joshua_sign to avoid usage of various third parts
# echo "Transferring the dump file $DUMPFILE from master $Mhost to slave $Shost via compressed rsync"
# rsync -vz $DUMPFILE $Shost:$DMPFILE
# echo "Importing the dump file ($DUMPFILE) into slave MySQL server $Shost"
# ssh $Shost "mysql --host=$Shost --port=$Sport --user=root --password=$rootpw < $DUMPFILE"
fn_echo "Import dumpfile $DUMPFILE into slave $Shost:$Sport ... (this may take a while)"
if [ $verbose -eq 1 ];then
if [ $showPasswords -eq 1 ];then
fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"mysql $SLAVE < $DUMPFILE\"";
else
fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"mysql $SLAVENOPW < $DUMPFILE\"";
fi
fi
mysql $SLAVE < $DUMPFILE
;;
#
*) usage ;;
esac
# Joshua-sign : fully init replication we need to construct query line like :
# CHANGE MASTER TO MASTER_HOST='192.168.1.4', MASTER_USER='replication_user', MASTER_PASSWORD='replication_pwd', MASTER_LOG_FILE='mysql-bin.004258', MASTER_LOG_POS=426927318;
# and play this on each MASTER and SLAVE (with the corrects values)
# Find out the master binlog file name and position
fn_echo "Update master information on Master..."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Catching the master_log_file and master_log_position on slave $Shost:$Sport by : \"SHOW MASTER STATUS\G;\""; fi
masterlogfile_formaster=$(echo "SHOW MASTER STATUS\G;" | mysql $SLAVE | grep "File:" | cut -d: -f2 | cut -d" " -f2)
masterlogpos_formaster=$(echo "SHOW MASTER STATUS\G;" | mysql $SLAVE | grep "Position:" | cut -d: -f2 | cut -d" " -f2)
if [ $verbose -eq 1 ];then
fn_echo "DEBUG - Catched 'master_log_file' on slave $Shost:$Sport : $masterlogfile_formaster"
fn_echo "DEBUG - Catched 'master_log_position' on slave $Shost:$Sport : $masterlogpos_formaster"
fi
if [ $verbose -eq 1 ];then
if [ $showPasswords -eq 1 ];then
fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"CHANGE MASTER TO MASTER_HOST='$Shost', MASTER_USER='$replication_user', MASTER_PASSWORD='$replication_pwd', MASTER_LOG_FILE='$masterlogfile_formaster', MASTER_LOG_POS=$masterlogpos_formaster;\"";
else
fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"CHANGE MASTER TO MASTER_HOST='$Shost', MASTER_USER='$replication_user', MASTER_PASSWORD='xxxxxxxxxx', MASTER_LOG_FILE='$masterlogfile_formaster', MASTER_LOG_POS=$masterlogpos_formaster;\"";
fi
fi
echo "CHANGE MASTER TO MASTER_HOST='$Shost', MASTER_USER='$replication_user', MASTER_PASSWORD='$replication_pwd', MASTER_LOG_FILE='$masterlogfile_formaster', MASTER_LOG_POS=$masterlogpos_formaster;" | mysql $MASTER
#
# Start the replication on slave
fn_echo "Starting slave replication on Slave $Shost...."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"START SLAVE;\""; fi
echo "START SLAVE;" | mysql $SLAVE
sleep 3
#
# Show slave status to see if all is in sync
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on slave $Shost:$Sport : \"SHOW SLAVE STATUS \G;\"";fi
echo "SHOW SLAVE STATUS \G;" | mysql $SLAVE
#
# Start the replication on master
fn_echo "Starting slave replication on Master $Mhost...."
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"START SLAVE;\""; fi
echo "START SLAVE;" | mysql $MASTER
sleep 3
#
# Show slave status to see if all is in sync
if [ $verbose -eq 1 ];then fn_echo "DEBUG - Performing on master $Mhost:$Mport : \"SHOW SLAVE STATUS \G;\""; fi
echo "SHOW SLAVE STATUS \G;" | mysql $MASTER
fn_echo "End of jobs."
fn_echo ""
fn_echo "If you experience error please read the solution at the begining of this file."
@joshuasign
Copy link
Author

joshuasign commented Jan 9, 2017

Hi all,

This script is a modified version of MySQL_REBUILD_LIVE_SLAVE_from_MASTER by Matthew Crenshaw,
I use it successfully on production servers when replication is broken.
I hope this will be usefull for anyone need it.

Have a good day!
Josh_

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment