Monday 21 May 2012

MySQL Replication

MySQL Replication

Two years ago, I had to learn MySQL replication because we had to transfer our databases to a new server with minimal downtime. If it's performed correctly, the downtime could be under 60 seconds. In my case, the downtime was about 5 minutes because of my carelessness. Nonetheless, MySQL replication can be used for many purposes including:
  1. Scalability - if most of your queries are read.
  2. Data security
  3. Analytics - there are cases when you have complex queries and you do not want to put the stress on the production server.
  4. Long-distance data distribution
Whatever your reason for coming here. Let's cut it short and start configuring.

Configuring the master server
  1. Master server must have binary log enabled
  2. Unique server-id must be configured
Edit my.cnf, for
  • Red Hat based server: /etc/my.cnf
  • Debian based server: /etc/mysql/my.cnf
Insert the following lines under [mysqld]:
[mysqld]
log-bin   = mysql-bin
server-id = 1
Make sure the following lines must be commented out. Otherwise, slave servers won't be able to access the master:
#skip-networking
#bind-address    = 127.0.0.1
Now, restart MySQL service:
Debian based:  service mysql restart
Red Hat based: /etc/init.d/mysqld restart
Create replication user on master server
  1. Log into MySQL server as root
    mysql -uroot -p
  2. Now, on MySQL shell create the replication user
    mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY 'password';
    mysql> FLUSH PRIVILEGES;
Configuring the slave server
  1. Unique server-id must be configured. Remember, none of the slave/master servers can have the same server-id. Server-id enabled communication between the master and slave servers.
  2. Enabling binary log is not compulsory but it recommended for data backup and crash recovery. There might be a case when you want this slave server to be the master server for other slaves.
  3. The following configurations can be set/changed whilst MySQL service is running:
    • master-host: master IP address or hostname.
    • master-user: MySQL user account with replication privilege.
    • master-password: replication user password.
    • master-connect-retry: seconds to retry to connect after network failure.
Edit my.cnf and insert the following lines under [mysqld]:
[mysqld]
log-bin               = mysql-bin
server-id             = 2
master-host           = 192.168.0.1
master-user           = slave_user
master-password       = password
master-connect-retry  = 60
Now, restart MySQL service.

Preparing to replicate
Most of the cases, we have our master database running long before the slave. Hence, the master database should have a lot of data. We must import data from master to slave before replicating. There are two ways:
  1. LOAD DATA FROM MASTER:
    use this if you are willing to have the master server being locked during the importing operation.
    1. Log into MySQL server as root:
      mysql -uroot -p
    2. Now, importing and replicating from MySQL shell:
      mysql> LOAD DATA FROM MASTER;
    Done! Life cannot be simpler than this!

  2. Common procedure:

    Tasks on master server

    1. Enabling READ LOCK from master server for mysqldump later. We want to make sure that data will not be changed while we dumping the databases:
      mysql> FLUSH TABLES WITH READ LOCK;
    2. Now, get the log sequence number:
      mysql> SHOW MASTER STATUS;
      If we see something like this, then we are on the right track:
      +------------------+----------+--------------+------------------+
      | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
      +------------------+----------+--------------+------------------+
      | mysql-bin.000001 |      106 |              |                  |
      +------------------+----------+--------------+------------------+
      1 row in set (0.00 sec)
      Please take note of the position (106)! This is the log position where we start backing up the data.
    3. Backup up the database from Linux shell:
      mysqldump --routines --triggers --single-transaction --quick -uroot -p --all-databases > all-dbs.sql
    4. Unlock the master database so data can be written:
      mysql> UNLOCK TABLES;
    5. Now, transfer SQL file (all-dbs.sql) to slave server.

    Tasks on slave server

    1. Import data to slave server:
      mysql -uroot -ppassword mysql < /path/to/all-dbs.sql
      Note: -ppassword: no space between -p & password
    2. Stop slave from replicating:
      mysql> SLAVE STOP;
    3. Now, we have to manually set the log sequence position:
      mysql> CHANGE MASTER TO
      MASTER_HOST='192.168.0.1',
      MASTER_USER='slave_user',
      MASTER_PASSWORD='password',
      MASTER_LOG_FILE='mysql-bin.001',
      MASTER_LOG_POS=106;
    4. Finally, start replicating:
      mysql> SLAVE START;
By now, our slave server should be replicating from the master server.

No comments: