GUOB Tech Day 2017

11 fevereiro 2015

Tutorial: Replicação MySQL em 5 minutos

A replicação é um recurso nativo do MySQL e tem vários usos, tais como como: backup, alta-disponibilidade, redundância e distribuição geográfica de dados, escalabilidade horizontal, etc... O melhor: configurar a replicação do MySQL é extremamente simples!

Para testar, vamos usar o Linux e configurar a replicação no MySQL 5.6 entre 2 instâncias: uma master e outra slave. Serão criadas 2 instâncias MySQL partir do zero, ou seja, sem dados. Elas estarão na mesma máquina, mas respondendo em portas diferentes: 3310 e 3311.


Pré-requisito

O único pré-requisito é ter o MySQL 5.6 instalado.
  • Se já tiver o MySQL 5.6 instalado, basta usar o caminho onde está o bin/mysqld como basedir nos passos abaixo. Por exemplo, no Oracle Linux 7 ou RHEL 7 o binário fica em /usr/sbin/mysqld, portanto basedir=/usr;
  • Caso ainda não tenha os binários do MySQL 5.6, basta baixar o arquivo TAR e descompactar em algum diretório conveniente que será seu basedir, como por exemplo /opt/mysql/mysql-5.6:
    • # mkdir /opt/mysql
    • # cd /opt/mysql
    • # wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.23-linux-glibc2.5-x86_64.tar.gz
    • # tar xvzf mysql-5.6.23-linux-glibc2.5-x86_64.tar.gz
    • # rm mysql-5.6.23-linux-glibc2.5-x86_64.tar.gz
    • # mv mysql-5.6.23-linux-glibc2.5-x86_64 mysql-5.6
    • Observações: neste caso considere para os passos abaixo basedir=/opt/mysql/mysql-5.6; tente trabalhar sempre com as versões mais recentes – substitua 5.6.23 nos comandos acima caso outra mais atual esteja disponível em http://dev.mysql.com/downloads/mysql .
Para um tutorial completo de como criar uma VM com MySQL para testes, veja http://www.alastori.com.br/2014/11/tutorial-ambiente-de-testes-com-mysql.html .

Replicação simples

1.   Crie uma instância para ser o Master:
# mkdir /opt/mysql/master /opt/mysql/master/data /opt/mysql/master/tmp
# cd /opt/mysql/master
# nano master.cnf
[client]
port=3310
socket=/opt/mysql/master/tmp/my-master.sock
[mysql]
prompt=master>\\_
[mysqld]
server-id=10
port=3310
basedir=/usr
datadir=/opt/mysql/master/data
socket=/opt/mysql/master/tmp/my-master.sock
log-bin=master-bin.log
innodb_flush_log_at_trx_commit=1
sync_binlog=1
# chown mysql:mysql *
# /usr/bin/mysql_install_db --defaults-file=/opt/mysql/master/master.cnf --user=mysql


2.   Inicie e teste a nova instância:
# /usr/bin/mysqld_safe --defaults-file=/opt/mysql/master/master.cnf &
# mysql --defaults-file=/opt/mysql/master/master.cnf -uroot -p
master> SHOW VARIABLES LIKE 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port       | 3310  |
+---------------+-------+
Observação: quando necessário, para parar o processo mysqld faça um shutdown limpo:
# mysqladmin --defaults-file=/opt/mysql/master/master.cnf -uroot –p shutdown


3.   Abra outro terminal e crie outra instância para ser o Slave:
# mkdir /opt/mysql/slave /opt/mysql/slave/data /opt/mysql/slave/tmp
# cd /opt/mysql/slave
# nano slave.cnf
[client]
port=3311
socket=/opt/mysql/slave/tmp/my-slave.sock
[mysql]
prompt=slave>\\_
[mysqld]
server-id=11
port=3311
basedir=/usr
datadir=/opt/mysql/slave/data
socket=/opt/mysql/slave/tmp/my-slave.sock
log-bin=slave-bin.log
innodb_flush_log_at_trx_commit=1
sync_binlog=1
# chown mysql:mysql *
# /usr/bin/mysql_install_db --defaults-file=/opt/mysql/slave/slave.cnf --user=mysql


4.   Inicie e teste a nova instância:
# /usr/bin/mysqld_safe --defaults-file=/opt/mysql/slave/slave.cnf &
# mysql --defaults-file=/opt/mysql/slave/slave.cnf -uroot -p
slave> SHOW VARIABLES LIKE 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port       | 3311  |
+---------------+-------+


5.   Agora que temos duas instâncias com server-id’s diferentes e log-bin habilitado, crie um usuário na instância master para que a slave consiga conectar-se a ela:
master> CREATE USER repl_user@127.0.0.1;
master> GRANT REPLICATION SLAVE ON *.* TO repl_user@127.0.0.1 IDENTIFIED BY 'repl_user_password';
Observação: em uma instalação real a instância slave provavelmente estará em outro host – substitua 127.0.0.1 pelo IP do host onde está sua instância slave.


6.   Antes de iniciar a replicação, verifique o status no master:
master> SHOW MASTER STATUS \G
*************************** 1. row ***************************
         File: master-bin.000003
     Position: 433


7.   Use os dados do status acima e inicie a replicação no slave:
slave> CHANGE MASTER TO
   MASTER_HOST='127.0.0.1',
MASTER_PORT=3310,
   MASTER_USER='repl_user',
   MASTER_PASSWORD='repl_user_password',
   MASTER_LOG_FILE='master-bin.000003',
   MASTER_LOG_POS=433;
slave> START SLAVE;


8.    Teste básico:
master> CREATE DATABASE teste_repl;
master> CREATE TABLE teste_repl.simples (id INT NOT NULL PRIMARY KEY);
master> INSERT INTO teste_repl.simples VALUES (999),(1),(20),(5);
slave> SELECT * FROM teste_repl.simples;

Conclusão



Como vimos, é muito simples fazer funcionar a replicação no MySQL. Mais adiante veremos opções mais avançadas para tornar a replicação mais resiliente a erros (crash-safe) e implementar failover automático.
Referências:

2 comentários:

Wagner disse...

Para criar 2 ou mais instancias do MySQL 5.7.11 será que funciona estes passos se eu mudar a função mysql_install_db (deprecated) para initialize? Seria muita diferença fazer este processo descrito com o MySQL 5.7?

Airton Lastori disse...

Wagner,

Sim. O mysql_install_db foi substituido pelo mysqld --initialize no MySQL 5.7. Se quiser fazer testes simples, sem definir senha para root use --initialize-insecure

Você pode testar desta forma:

## Passo 1 - crie 3 instancias MySQL
mysqld --no-defaults --user=mysql --initialize-insecure \
--explicit_defaults_for_timestamp --datadir=/tmp/mysqldata1 \
--log-error=/tmp/mysqldata1/mysqld1.log --sql-log-bin=0

mysqld --no-defaults --user=mysql --datadir=/tmp/mysqldata1 -P 13001 \
--log-error=/tmp/mysqldata1/mysqld1.log --socket=mysqld1.sock &
sleep 8
ps -ef |grep mysqld

mysqladmin -uroot -h 127.0.0.1 -P 13001 -u root shutdown
sleep 8
ps -ef |grep mysqld

cd /tmp
rm mysqldata1/auto.cnf
cp -R mysqldata1 mysqldata2
chown -R mysql:mysql mysqldata2
cp -R mysqldata1 mysqldata3
chown -R mysql:mysql mysqldata3


## Passo 2 - subir as 3 instancias MySQL
mysqld --no-defaults --user=mysql --datadir=/tmp/mysqldata1 -P 13001 \
--log-error=/tmp/mysqldata1/mysqld1.log \
--socket=mysqld1.sock &

mysqld --no-defaults --user=mysql --datadir=/tmp/mysqldata1 -P 13002 \
--log-error=/tmp/mysqldata2/mysqld2.log \
--socket=mysqld2.sock &

mysqld --no-defaults --user=mysql --datadir=/tmp/mysqldata3 -P 13003 \
--log-error=/tmp/mysqldata3/mysqld3.log \
--socket=mysqld3.sock &

## Passo 3 - conectar as instancias MySQL
mysql -uroot -h 127.0.0.1 -P 13001
mysql -uroot -h 127.0.0.1 -P 13002
mysql -uroot -h 127.0.0.1 -P 13003