InnoDB-Cluster

Da wiki.gienne.cloud.
#!/bin/sh
###### Script di configurazione
## File necessari: 
## Mysql TAR principale
## Mysql Shell
####################

mkdir -p /opt/mysql/etc
mkdir -p /opt/mysql/dump
mkdir -p /opt/mysql/tmp
mkdir -p /opt/mysql/etc
mkdir -p /opt/mysql/pid
mkdir -p /opt/mysql/logs
mkdir -p /opt/mysql/data

 

cp /mysql/my.cnf /opt/mysql/etc


cd /mysql
cp mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz /opt/mysql
cd /opt/mysql
tar -xvzf mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz
rm /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz


ln -s /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64/bin /opt/mysql/bin
ln -s /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64/docs /opt/mysql/docs
ln -s /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64/include /opt/mysql/include
ln -s /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64/lib /opt/mysql/lib
ln -s /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64/man /opt/mysql/man
ln -s /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64/share /opt/mysql/share
ln -s /opt/mysql/mysql-5.7.21-linux-glibc2.12-x86_64/support-files /opt/mysql/support_files

cd /mysql
tar -xvzf mysql-shell-1.0.11-linux-glibc2.12-x86-64bit.tar.gz
cp mysql-shell-1.0.11-linux-glibc2.12-x86-64bit/bin/* /opt/mysql/bin


echo export MYSQL_HOME=/opt/mysql >> /home/mysql/.profile
echo PATH="\$PATH:\$MYSQL_HOME/bin" >> /home/mysql/.profile

echo export https_proxy=http://127.0.0.1:3128 echo export http_proxy=http://127.0.0.1:3128

wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz

echo #!/bin/bash > /home/mysql/.bashrc
echo "source /home/mysql/.profile" >> /home/mysql/.bashrc



mysqld --defaults-file=/opt/mysql/etc/my.cnf --initialize --innodb-log-group-home-dir=/opt/mysql/logs --innodb_data_file_path=ibdata1:2048M



echo "-----------------------------------Comandi Utili----------------"
echo "mysql -h 127.0.0.1 -u root -p"
echo "SET PASSWORD = 'orione';"
echo "show variables like "character_set_database";"
echo "SHOW ENGINES;"
echo "mysqld --defaults-file=/opt/mysql/etc/my.cnf &" 



group_replication_group_seeds

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

## https://dev.mysql.com/doc/refman/5.7/en/group-replication-launching.html

SET GLOBAL group_replication_bootstrap_group=ON;




GRANT ALL ON *.* to 'clu_adm'@'%' IDENTIFIED BY 'ewrjl23434asd3' WITH GRANT OPTION;

GRANT ALL PRIVILEGES ON mysql_innodb_cluster_metadata.* TO clu_adm@'%' WITH GRANT OPTION;
GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, \
CREATE USER ON *.* TO clu_adm@'%' WITH GRANT OPTION;
GRANT SELECT ON *.* TO clu_adm@'%' WITH GRANT OPTION;





mysqlsh --log-level=DEBUG3
mysql-js> dba.verbose=2

 dba.checkInstanceConfiguration('clu_adm@mui-mysvmxpoca1:3306')

 dba.checkInstanceConfiguration('clu_adm@mui-mysvmxpoca1:3306')
 dba.checkInstanceConfiguration('clu_adm@mui-mysvmxpoca1:3306')









echo Autocommit controllare e mettere uguale  ad oracle

echo "DUMP SLAVE verificare dopo il cluster"


cd /opt/mysql/mysql-shell-1.0.11-linux-glibc2.12-x86-64bit
cd bin
cp * /opt/mysql/bin/
cd ..
cd share
cp -r * /opt/mysql/share/

# Verificare: /usr/bin/env python


# MySQL Shell provides two scripting language modes, JavaScript and Python, 
# in addition to a native SQL mode. Throughout this guide MySQL Shell is used primarily in JavaScript mode . 
# When MySQL Shell starts it is in JavaScript mode by default. Switch modes by issuing \js for JavaScript mode,
# \py for Python mode, and \sql for SQL mode. Ensure you are in JavaScript mode by issuing the \js command, then execute:
# mysql-js> dba.deploySandboxInstance(3310)



############# Da analizzare: per utente sola lettura.
# GRANT SELECT ON mysql_innodb_cluster_metadata.* TO your_user@'%';
# GRANT SELECT ON performance_schema.global_status TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_applier_configuration TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_applier_status TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_applier_status_by_coordinator TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_applier_status_by_worker TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_connection_configuration TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_connection_status TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_group_member_stats TO your_user@'%';
# GRANT SELECT ON performance_schema.replication_group_members TO your_user@'%';
## Da Mysqlsh fare il check della configurazione:
## dba.checkInstanceConfiguration('root@localhost:3306')
## dba.configureLocalInstance('root@localhost:3306')
\connect clu_adm@mui-mysvmxpoca1:3306
dba.configureLocalInstance('clu_adm@mui-mysvmxpoca1:3306')

\connect clu_adm@mui-mysvmxpoca2:3306
dba.configureLocalInstance('clu_adm@mui-mysvmxpoca1:3306')

\connect clu_adm@mui-mysvmxpoca3:3306
dba.configureLocalInstance('clu_adm@mui-mysvmxpoca1:3306')

mysql-js> dba.configureLocalInstance('clu_adm@localhost:3306')
Please provide the password for 'clu_adm@localhost:3306':


ewrjl23434asd3

dba.configureLocalInstance('clu_adm@locals'
bash
dba.configureLocalInstance('clu_adm@localhost:3306')

 dba.checkInstanceConfiguration('clu_adm@mui-mysvmxpoca1lds
 :3306')

Detecting the configuration file...
Found configuration file at standard location: /etc/my.cnf
Do you want to modify this file? [Y|n]:  [Y|n]: n
Default file not found at the standard locations.
Please specify the path to the MySQL configuration file: /opt/mysql/etc/my.cnf
Validating instance...

The instance 'localhost:3306' is valid for Cluster usage
You can now use it in an InnoDB Cluster.

{
    "status": "ok"
}
mysql-js>







\connect root@localhost:3306
#ewrjl23434asd3 
my
var cluster=dba.createCluster('PocTest');
var cluster=dba.getCluster('PocTest')

forceQuorumUsingPartitionOf

cluster.describe()
cluster.status()

1:
2:
3:
 var cluster = dba.rebootClusterFromCompleteOutage();


#PASSWORD CREATA: hkZQMDgmg2
cluster.status();

dba.rebootClusterFromCompleteOutage('PocTest') 
 dba.configureLocalInstance('root@localhost:3306')
 mysqlsh --uri cluadm@mui-mysvmxpoca1:3306
 


cluster = dba.getCluster("PocTest")



\connect clu_adm@mui-mysvmxpoca1:3306
var cluster = dba.createCluster('prodCluster')
cluster.checkInstanceState('clu_adm@mui-mysvmxpoca3:3306')

cluster.rejoinInstance('clu_adm@mui-mysvmxpoca3:3306')

cluster.checkInstanceState('clu_adm@mui-mysvmxpoca2:3306')
dba.validateInstance('clu_adm@mui-mysvmxpoca2:3306')mcs 
cluster.checkInstanceState('clu_adm@mui-mysvmxpoca2:3306')
cluster.checkInstanceState('clu_adm@mui-mysvmxpoca3:3306')
cluster.addInstance('clu_adm@mui-mysvmxpoca1:3306')
cluster.addInstance('clu_adm@mui-mysvmxpoca2:3306')

cluster.addInstance('clu_adm@mui-mysvmxpoca3:3306')

dba.configureLocalInstance('clu_adm@mui-mysvmxpoca2:3306')
cluster.checkInstanceState('clu_adm@mui-mysvmxpoca3:3306')

dba.checkInstanceConfiguration()
dba.checkInstanceConfiguration('clu_adm@mui-mysvmxpoca1:3306')
./mysqlrouter --bootstrap clu_adm@mui-mysvmxpoca1:3306 --directory /opt/mysql/router/etc
Inizializzaione
unzip
mkdir 
cluster.checkInstanceState('clu_adm@mui-mysvmxpoca2:3306')
\connect clu_adm@mui-mysvmxpoca1:3306
var cluster=dba.getCluster('PocTest');

cluster.describe()
cluster.status()

cluster.checkInstanceState('clu_adm@mui-mysvmxpoca3:3306')

cluster.rejoinInstance('clu_adm@mui-mysvmxpoca3:3306')
./mysqlrouter --bootstrap clu_adm@mui-mysvmxpoca1:3306 --directory /opt/mysql/router/etc

shell.connect('clu_adm@mui-mysvmxpoca1:3306');
var cluster = dba.rebootClusterFromCompleteOutage();
cluster.forceQuorumUsingPartitionOf('clu_adm@mui-mysvmxpoca3:3306')

ewrjl23434asd3
cluster.rejoinInstance('clu_adm@mui-mysvmxpoca2:3306')
cluster.removeInstance('clu_adm@mui-mysvmxpoca2:3306')
cluster.removeInstance('clu_adm@mui-mysvmxpoca1:3306')
######
cluster.removeInstance('clu_adm@mui-mysvmxpoca3:3306')

cluster.removeInstance(clu_adm@mui-mysvmxpoca2:3306)

log = /opt/mysql/mysqld.log
log-error = /opt/mysql/mysqld.error.log

Amministrazione (FAQ)
Come si controlla lo stato del cluster?
Utilizzando i seguenti comandi MySQL Shell:
\connect clu_adm@mui-mysvmxpoca1:3306
var cluster = dba.getCluster("myCluster")

cluster.describe()
cluster.status()

cluster.checkInstanceState('xeniadb01.xenialab.it:3306')

Ovviamente e' lo stato del cluster il piu' importante... se c'e' OK va bene! Nel seguito riportiamo qualche dettaglio in piu' sugli stati del cluster

Come si interrompe e riavvia la replica su un nodo?
Con gli stessi comandi previsti per la Group Replication:

STOP GROUP_REPLICATION;

START GROUP_REPLICATION;

Come si disconnette temporaneamente un nodo dal cluster?
Vi sono diversi motivi per farlo: ad esempio per riconfigurare qualche parametro di tuning... I passi corretti sono:
STOP GROUP_REPLICATION;
mysqladmin shutdown (o equivalenti)
Per riconnettere il nodo:
cluster.rejoinInstance('root:xxx@xeniadb2.xenialab.it:3306')
Come si aggiungono nuovi nodi/istanze al cluster?
Ma allora non siete stati attenti: lo abbiamo gia' fatto!

dba.configureLocalInstance('root@localhost:3306')

dba.checkInstanceConfiguration('root:xxx@xeniadb4.xenialab.it:3306')
cluster.addInstance("root:xxx@xeniadb4.xenialab.it:3306")

In realta' la procedura indicata funziona solo se si hanno a disposizione tutti i binlog... Altrimenti si deve partire da un backup esattamente come avviene per la replica GTID
Come si rimuove un'istanza dal cluster?
Cosi':

cluster.removeInstance("root@localhost:3330")

In caso di disconnessione di un nodo come lo si riconnette al cluster?
Se l'intervallo di tempo e' breve la riconnessione avviene in automatico. Ma in caso di riavvio dell'istanza o di failure il nodo va riconnesso al cluster con:

cluster.rejoinInstance('root:xxx@xeniadb2.xenialab.it:3306')

E' molto importante sottolineare che non e' necessario effettuare alcuna verifica sui dati o sull'allineamento della replica. Questo avviene in modo completamente automatico.
Sono caduti piu' nodi, come si ricostituisce il cluster?
Nel caso in cui siano caduti meno nodi della tolleranza si riconnettono le istanze come visto nel punto precedente:

cluster.rejoinInstance('root:xxx@xeniadb2.xenialab.it:3306')

Se invece viene perso il Quorum il cluster non consente piu' operazioni in scrittura sui dati (per evitare corruzioni). Per ripristinare l'accesso e' necessario il comando:

cluster.forceQuorumUsingPartitionOf("root:xxx@xeniadb1.xenialab.it:3306")

Attenzione a non generare situazioni di Split Brain! 
Bisogna verificare che non vi siano altri nodi attivi prima di forzare il riavvio di una partizione del cluster. 
Una volta eseguito il comando i nodi non raggiungibili passano dallo stato UNREACHABLE a MISSING ed e' nuovamente possibile effettuare operazioni di scrittura sul DB.

E' caduto tutto ed il cluster non riparte. Che faccio?
Non dovrebbe succedere [NdA che cadano tutti i nodi]... ma, risolti i problemi di base, si deve ripartire con:

shell.connect('root:xxx@xeniadb1.xenialab.it:3306');
var cluster = dba.rebootClusterFromCompleteOutage();

E' "corretto" che il cluster non riparta da solo! 
Anche in questo caso attenzione a non generare situazioni di Split Brain!

Se non funziona va ricreato il Cluster da zero [NdA cluster.dissolve({force: true}) Attenzione: cancella tutto].

La situazione del cluster ora e' corretta ma il Router non lascia accedere...
Non dovrebbe succedere... ma un bel riavvio del Router risolve tutto [NdA richiede pochissimo tempo]:

systemctl restart mysqlrouter

Quale e' lo stato di dettaglio del cluster?
Ci sono diversi punti di vista...
Dal punto di vista dello stato della replica la situazione puo' essere:

OK : ovviamente e' tutto a posto!
OK_PARTIAL : qualche nodo non e' disponibile ma il cluster tollera ulteriori failure.
OK_NO_TOLERANCE : ci sono dei nodi non attivi ed un'ulteriore rottura porrebbe il cluster in situazione degradata.
NO_QUORUM : non e' possibile formare la maggioranza di nodi: il cluster puo' operare in sola lettura. I dati sono comunque corretti e sicuri su almeno un nodo.
UNKNOWN : stato del cluster come visto da un'istanza non ONLINE.
Dal punto di vista delle singole istanze queste hanno diversi stati (quando viste da se stesse): Stati InnoDB Cluster
ONLINE : ovviamente e' tutto a posto!
RECOVERING : il nodo sta entrando in un gruppo effettuando il recupero delle transazioni.
OFFLINE : il plugin e' stato caricato ma il nodo non e' configurato.
ERROR : ovviamente c'e' un problema!
Le istanze hanno stati diversi quando viste dall'esterno:
ONLINE : ovviamente e' tutto a posto!
RECOVERING : il nodo sta entrando in un gruppo effettuando il recupero delle transazioni.
UNREACHABLE : il nodo non e' piu' visibile dagli altri componenti del gruppo.
(MISSING) : il nodo non e' raggiungibile [NdA perche' non ancora attivato].
Le istanze possono essere in modalita' R/W (read and writable) o R/O (read only).
Lo stato di dettaglio della Group Replication si verifica con semplici SELECT sul performance_schema:

SELECT * FROM performance_schema.replication_group_members;
SELECT * FROM performance_schema.replication_group_member_stats;
SELECT * FROM performance_schema.replication_applier_status;

SHOW BINLOG EVENTS;
Dal punto di vista delle applicazioni tutti gli stati riportati sono indifferenti: il MySQL Router indirizza sempre i client verso l'istanza corretta. Nel caso in cui il nodo cui si e' connessi abbia un fault basta effettuare una riconnessione e si viene indirizzati ad un nodo funzionante.

Si puo' modificare la configurazione della Group Replication senza usare i comandi MySQL Shell?
Non e' consigliato. 
Tuttavia e' possibile modificare manualmente ogni configurazione. Il problema e' che eventuali variazioni sulle istanze non saranno contenute nel Meta Database. Per riallineare la configurazione:

cluster.rescan()

Un nodo non vuole entrare nel gruppo?
Per controllare se un nodo ha l'impostazione corretta si utilizza il comando dba.checkInstanceConfiguration(). I principali controlli sono relativi ai parametri di configurazione ed alla presenza di sole tabelle InnoDB con chiave primaria. Ecco le query utilizzabili per verificare quest'ultimo requisito:
SELECT table_schema, table_name, engine
  FROM information_schema.tables
 WHERE engine NOT IN ('InnoDB', 'MEMORY')
   AND table_schema NOT IN ('mysql', 'performance_schema', 'information_schema');

SELECT t.table_schema, t.table_name
  FROM information_schema.tables t
       LEFT JOIN information_schema.table_constraints c 
              ON t.table_schema = c.table_schema         
             AND t.table_name = c.table_name
 WHERE t.table_type = 'BASE TABLE'
   AND t.table_schema NOT IN ('mysql', 'performance_schema', 'information_schema')
 GROUP BY t.table_schema, t.table_name
HAVING sum(if(c.constraint_type='PRIMARY KEY', 1, 0)) = 0;
L'elenco completo dei controlli e' riportato in questo script.

Difficili da diagnosticare sono i problemi legati al networking. DNS, reverse lookup, file hosts, white list, ... possono ingannare: come un nodo viene chiamato o come pensa di chiamarsi e' molto importante!

Ulteriori problemi e work around sono descritti con la Group Replication.


luster.rejoinInstance: ERROR: 1 table(s) do not have a Primary Key or Primary Key Equivalent (non-null unique key).
ERROR: Error joining instance to cluster: The operation could not continue due to the following requirements not being met:
Non-compatible tables found in database. (RuntimeError)
mysql-js> cluster.rejoinInstance('clu_adm@mui-mysvmxpoca2:3306')
Rejoining the instance to the InnoDB cluster. Depending on the original
problem that made the instance unavailable, the rejoin operation might not be
successful and further manual steps will be needed to fix the underlying
problem.

Please monitor the output of the rejoin operation and take necessary action if
the instance cannot rejoin.

Please provide the password for 'clu_adm@mui-mysvmxpoca2:3306':
Rejoining instance to the cluster ...

Cluster.rejoinInstance: Access denied for user 'clu_adm'@'mui-mysvmxpoca1.unix.masad.it' (using password: YES) (MySQL Error 1045)



https://community.oracle.com/thread/4085689