How to add a new MySQL slave

This post explains how to add a new slave to the existing MySQL replication. New slave server can be added to the MySQL replication without stopping master or shutting down existing slave server. You will have to temporarily stop replication on the slave server in order to take the current data snapshot. On the other hand, if you need to set up a new MySQL replication, please read dev.mysql.com - How to Set Up Replication

Contents
  1. Stop replication on the existing slave
  2. Export databases from the existing slave
  3. Copy relay-log.info and master.info from existing to the new slave server
  4. Start replication on the existing slave
  5. Import MySQL dump to the new slave server and stop mysqld
  6. Edit relay-log.info file
  7. Add grant on the master server
  8. Copy my.cnf and increment server-id
  9. Start a new slave server



1. Stop replication on the existing slave
To clone a new slave server, it is necessary to temporary stop replication on the existing slave. Why? Because you will have to take a data snapshot. Connect to the slave using MySQL client and run the following command:

# (existing slave server) pause replication
mysql> show slave status\G
mysql> slave stop;
mysql> show slave status\G

Existing slave is only paused and every change from the master will wait until you start replication with slave start command. Slave server will normally execute SQL requests and if your data changes are not so frequent, no one will notice that something is happening in the background. With show slave status you will see the status report before and after slave is stopped.



2. Export databases from the existing slave
After existing slave is paused, you can take a data snapshot. With mysqldump, database (or a collection of databases) can be exported to the file.

# (existing slave server) export database to the file
bash> mysqldump -p -uroot my_database > /tmp/my_database.sql

Before running mysqldump, be sure you have enough disk space. Move my_database.sql to the new slave server using scp, ftp, wget ...



3. Copy relay-log.info and master.info from existing to the new slave server
A slave replication server creates two additional small files in the data directory. These status files are named relay-log.info and master.info by default. relay-log.info contains relay_log file name, relay_log position, corresponding master log name and corresponding master log position, while master.info contains parameters to connect to the master server: server address, user to connect to the master server (with plain text password), port ... Here is example how you can copy relay-log.info and master.info to the new slave server:

# (existing slave server) copy relay-log.info and master.info files
bash> scp   /var/lib/mysql/relay-log.info   new_slave_server:/var/lib/mysql
bash> scp   /var/lib/mysql/master.info      new_slave_server:/var/lib/mysql



4. Start replication on the existing slave
Data snapshot, relay-log.info and master.info are copied to the new slave server. Now you can start replication on the existing slave.

# (existing slave server) start replication
mysql> show slave status\G
mysql> slave start;
mysql> show slave status\G

New slave server can wait because it will retrieve changes from the point written in its relay-log.info file.



5. Import MySQL dump to the new slave server and stop mysqld
You have already move MySQL dump to the new slave server. To import data to the MySQL database, use mysql client.

# (new slave server) import database from the file
bash> mysql -p -u root my_database < /tmp/my_database.sql

After data import is finished, stop mysqld because you will need to change relay-log.info and create /etc/my.cnf file. I will just mention that you can run data import from the existing slave directly - without coping first, but you will have to grant access from the existing slave server. The only difference is a -h switch.

# (existing slave server) import database from the file
bash> mysql -p -u root -h new_slave_server my_database < /tmp/my_database.sql



6. Edit relay-log.info file
As said before, relay-log.info contains relay_log file name. By default, relay log file names have the form host_name-relay-bin.nnnnnn, where host_name is the name of the slave server host and nnnnnn is a sequence number. The new slave server will have a new name and that change should be included. Open relay_log.info file and edit the first line.

# (new slave server) change relay_log file name in relay-log.info

# first line before change
./existing_slave_name-relay-bin.000076

# first line after change
./new_slave_name-relay-bin.000001

You can reset sequence number because mysqld will recreate relay_log after starting up. If you get the following errors after starting the new slave server:

  • Failed to open the relay log
  • Could not find target log during relay log initialization

you are probably entered a wrong host_name.



7. Add grant on the master server
Each slave must connect to the master using a standard MySQL user name and password, so there must be a user account on the master that the slave can use to connect. In this scenario with existing slave, user for replication already exist on the master server. You will only have to set additional grant. Let's assume that user name for replication is replica:

# (master server) add grant to replica user to connect from the new slave server
mysql> grant replication slave on *.* to 'replica'@'new_slave_name' identified by 'password';

With this grant, replica user could only request updates that have been made to databases on the master server - nothing more.



8. Copy my.cnf and increment server-id
On the master and each slave, you must use the server-id option to establish a unique replication ID. For each server, you should pick a unique positive integer, and each ID must be different from every other ID. Copy /etc/my.cnf from the existing slave to the new slave and edit server-id line. In my example, master is server-id=1 and the first slave is server-id=2, so I set server-id=3 to the new slave server.



9. Start a new slave server

# (new slave server) start replication
bash> /etc/init.d/mysqld start
# or
bash> service mysqld start

If all went according to this cookbook, in /var/log/mysqld.log, you should find:

  • Slave SQL thread initialized, starting replication in log ...
  • Slave I/O thread: connected to master 'replica@your_master:3306', replication started in log ...

... means that you have successfully add a new slave server.

Bookmark and Share

5 Responses to “How to add a new MySQL slave”

  1. When editing the relay-log.info file, it's not enough to only edit the name of the relay log, but the position should be changed as well (to 0). If you don't, the slave will start reading at a later point in it's relay log.

    But better then to edit the file it is to delete them both, and to initialize the slave with "CHANGE MASTER TO", which values can be read from the master.info file.

  2. dbunic says:

    Stijn van der Ree,
    I read once again MySQL manual pages Replication Relay and Status Files and you have right. Not only name should be changed but position too. On the other hand, I'm sure that I didn't touch Relay_Log_Pos (second line) in relay-log.info file, only name was changed as I described in Edit relay-log.info file. Hmm, the question is how did I successfully create a new MySQL slave if position was not set to zero? I can only suppose that MySQL slave ignored non existing position in newly created new_slave_name-relay-bin.000001 file.

    Hope that someone can confirm my assumption.
    Cheers!

  3. At first I also only changed the filename, and then discovered the slave was missing some data. In my case it did start reading later on, maybe because the position in the relay-log already existed (because enough data was already downloaded from the master). It's likely that if the position does not exist, it starts at zero.

  4. Gavin Towey says:

    I agree with Stijin. I do this kind of thing all the time, and find it much better to read the position from the stopped slave, and use CHANGE MASTER TO, to initialize the new slave.

    In step one, just do SHOW SLAVE STATUS \G
    and record Relay_Master_Log_File and Exec_Master_Log_Pos

    It's very very important that it's those two, and not some of the other fields that look like they might be the master position. Because those define the position on the master it's actually exectued on the slave.

    Then just use CHANGE MASTER TO. That lets mysql manage it's master.info and such w/out the chance for messing up those files. The other advantages are that it can be done through the mysql client, instead of mucking around in files on the new slave, and you don't have to restart mysql on the new slave -- assuming you have slave-id set before you start.

Leave a Reply