Geoff Garside

Mar 10 2009

Setting up MySQL Replication

Today I was asked to set up a MySQL Replication server to allow for failover on one of the services we operate.

A friend of mine also asked me to document the procedure as its been a while since he’d done it and couldn’t remember. So here goes….

The Setup

I’ll be doing all of this on FreeBSD 7.1 servers and I’ll be installing things from ports and then setting up the replication part.

Installing MySQL is pretty much a breeze, I do tend to do this first though

# cat <<EOF > /etc/make.conf
.if ${.CURDIR:M*/databases/mysql5*}
BUILD_OPTIMIZED=YES
.endif
EOF

to ensure that MySQL is built to run as quickly as possible. Then you have the simple commands to install the server, assuming you use ports-mgmt/portupgrade

# portinstall databases/mysql50-server

once that has been done on each server then we can begin setting up the replication service.

Instruct the Master

First we need to tell the master that it is a master, we also need to make sure that it’ll listen for slaves. So we need to add some things to the configuration file. You can use /etc/my.cnf which is pretty global but I’ve opted for /var/db/mysql/my.cnf

[mysqld]
bind-address      = 192.168.0.10
server-id         = 1

now, it will listen and it knows its the master.

Next we need to instruct it where to keep the binary log file for replaying to the slaves so in the same file

log-bin           = mysql-bin
expire-logs-days  = 20
max_binlog_size   = 104857600

so the binary log file will be written to /var/db/mysql/mysql-bin, entries older than 20 days should be dropped and it shouldn’t grow bigger than 100 megabytes.

Finally we tell it exactly which databases we want to replicate, can you ignore this if you don’t want to be specific. Again in the same file

binlog-do-db      = testdb
binlog-ignore-db  = mysql,test

so only our testdb table will be binary logged, additionally mysql and test databases will be ignored.

Now you can restart your MySQL master server, to check that things are working you can connect to the server and run

mysql> SHOW MASTER STATUS;
+------------------+----------+---------------+-----------------------+
| File             | Position | Binlog_Do_DB  | Binlog_Ignore_DB      |
+------------------+----------+---------------+-----------------------+
| mysql-bin.000001 |       98 | testdb,testdb | mysql,test,mysql,test | 
+------------------+----------+---------------+-----------------------+
1 row in set (0.01 sec)

and you should get something like above. You can also check to make sure the server is listening for connections with

# sockstat | grep mysql | grep tcp4
mysql    mysqld     90119 13 tcp4   192.168.0.10:3306   *:*

Creating a replication user

So we need to setup an account on the master server for the slave to use to authenticate itself. To do this we create a REPLICATION SLAVE using the following MySQL statement

GRANT REPLICATION SLAVE ON *.* TO 'slave'@'slavehost' IDENTIFIED BY 'slavepass';

we’ll set these values on the slave as well so that it can authenticate to the master.

Instructing the Slave

Again I’ll be keeping my configuration in /var/db/mysql/my.cnf, so for the slave we need to tell it that it isn’t top of the food chain and also who is. To do this we add

[mysqld]
bind-address          = 192.168.0.11
server-id             = 2

to tell the Slave to listen for connections, this is so that external services which perhaps only need read access to the database can use the slave and save the master for writes.

Next we must inform the Slave of its masters address and its authentication credentials for use when addressing the Master

master-host           = 192.168.0.10
master-user           = slave
master-password       = slavepass
master-connect-retry  = 60

Finally as we only want one database to be replicated, in my case at least, add the following line to the configuration file

replicate-do-db       = testdb

so that only the testdb database will be replicated.

Copying the database to the Slave

Firstly we need to know where in the binlog we are at the moment, so on the master server run the following command

mysql> SHOW MASTER STATUS;
+------------------+----------+---------------+-----------------------+
| File             | Position | Binlog_Do_DB  | Binlog_Ignore_DB      |
+------------------+----------+---------------+-----------------------+
| mysql-bin.000001 |   327128 | testdb,testdb | mysql,test,mysql,test | 
+------------------+----------+---------------+-----------------------+

remember the File and Position values as we’ll need these to resynchronised the databases once the slave has a copy of the data.

Using mysqldump create a copy of the master database to put onto the slave

# mysqldump --opt --databases testdb > /root/master-databases.sql

Now copy the /root/master-databases.sql file to the slave and then import it, assuming you copied it to /root/master-databases.sql on the slave as well

# mysql < /root/master-databases.sql

Now we need to synchronise the two copies. On the slave load up the mysql client

mysql> STOP SLAVE;
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.0.10',
    -> MASTER_USER = 'slave_user', MASTER_PASSWORD = 'slave_pass',
    -> MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 327128;
mysql> START SLAVE;

and the changes will be synchronised between the two servers.

A quick test

Now its a good idea to make some test insertions into the master database and then check to see if they exist on the slave as well. I’ll leave this part up to you…

Comments
blog comments powered by Disqus