martedì 16 settembre 2014

Mysql Mirroring su Debian

Il problema: creare due database su due server differenti (master 192.168.1.1 e slave 192.168.1.2) in cui il secondo risulta essere la copia del primo
Si parte dal presupposto che entrambe abbiamo mysql installato (apt-get install mysql-server mysql-client) ed in funzione




Per la configurazione di base di Debian la porta 3306 risulta filtrata per cui sulla macchina master e' necessario modificare le regole di iptables. Per non abbassare troppo la guardia la porta 3306 e' aperta solo per le connessioni che provengono dallo slave

/sbin/iptables -A INPUT -i eth0 -s 192.168.1.1 -p tcp --destination-port 3306 -j ACCEPT
a questo punto ci sono due sistemi (si parte considerando database vuoti)

Sistema completo

Macchina Master
si edita il file /etc/mysql/my.cnf modificando
---------------------------------
bind-address = 192.168.1.1
server-id = 1 (basta decommentare)
log_bin = /var/log/mysql/mysql-bin.log (basta decommentare)
binlog_do_db = mirrdatabase (e' il nome del database su cui fare mirroring
---------------------------------

si riavvia il servizio mysql e  si entra in shell mysql (mysql -u root -p). 
Si crea un database 
CREATE DATABASE mirrdatabase;

A questo punto si crea un utente (slave_user) con password con privilegi di replica 

GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;

a questo punto si digita il comando 
SHOW MASTER STATUS;
che risponde qualcosa di simile a questo
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      1080| mirrdatabase |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
si annotino il numero di posizione ed il file perche' serviranno per la configurazione dello slave

Macchina Slave
si edita il file /etc/mysql/my.cnf modificando
---------------------------------
server-id = 2 
relay-log = /var/log/mysql/mysql-relay-bin.log
log_bin = /var/log/mysql/mysql-bin.log (basta decommentare)
binlog_do_db = mirrdatabase (e' il nome del database su cui fare mirroring
---------------------------------
si riavvia il servizio mysql e si entra in shell mysql (mysql -u root -p). e si crea il database
CREATE DATABASE mirrdatabase;


si digita quindi
CHANGE MASTER TO MASTER_HOST='192.168.1.1',MASTER_USER='slave_user', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS= 1080;

i valori in giallo sono ricopiati da quelli del master. A questo punto si attiva la replicazione (per essere sicuri che ci sia connessione tra le due macchine puo' essere comodo prima verificare con il comando mysql -h 192.168.1.1 -u slave_user -p che ci sia accesso alla shell di mysql)
Si avvia quindi la replicazione con il seguente comando

START SLAVE;
a questo punto tutti i comandi eseguiti sulla macchina Master saranno replicati sulla macchina Slave compresi quelli di creazione di tabelle o popolazione dei dati


Sistema speditivo
Con il metodo speditivo e' necessario che sulle due macchine siano presenti e gia' configurati database e strutture tabelle identiche. Per popolare i dati si puo' usare uno script Php con due connessioni (una verso localhost, l'altra verso la macchina di copia)

<?php 
$dbmaster = 'localhost'; 
$dbusermaster = 'root1'; 
$dbpassmaster = 'password1'; 
$dbslave = '192.168.1.2'; 
$dbuserslave = 'root2'; 
$dbpassslave = 'password2'; 


$conn_master = mysql_connect($dbmaster, $dbusermaster, $dbpassmaster); 
if(! $conn_master ) 
      { 
      die('Could not connect: ' . mysql_error()); 
      } 
$conn_slave = mysql_connect($dbslave, $dbuserslave, $dbpassslave); 
if(! $conn_slave ) 
      { 
      die('Could not connect: ' . mysql_error()); 
      } 



$sql = 'INSERT INTO employee '. '(emp_name,emp_address, emp_salary, join_date) '. 'VALUES ( "guest", "XYZ", 2000, NOW() )'; 
mysql_select_db('mirrdatabase'); 

$retval = mysql_query( $sql, $conn_master ); 
if(! $retval ) 
      { 
      die('Could not enter data in master: ' . mysql_error()); 
      } 

$retval2 = mysql_query( $sql, $conn_slave ); 
if(! $retval2 ) 
      { 
      die('Could not enter data in slave : ' . mysql_error()); 
      } 

echo "Entered data successfully\n"; 
mysql_close($conn_master); 
mysql_close($conn_slave); 
?>