The following picture shows how the mariadb replication is deployed:
Two mariadb servers are deployed: one is master and another one is slave.
Above the mariadb servers, MaxScale is deployed. It is used to monitor the status of the mariadb servers. If the mariadb master node is down, the MaxScale will promote the slave as master. And after the previous master mariadb server is started, it will become to slave node.
The MaxScale also acts as a proxy of the mariadb servers and it ensures all the database write requests will go to the master mariadb server.
In the node 192.168.0.1 and node 192.168.0.2, the mariadb server docker image and maxscale docker image will be pulled.
# docker pull mariadb:10.3
# docker pull mariadb/maxscale:2.3
The node 192.168.0.1 is assumed as master and the node 192.168.0.2 is assumed as slave.
Create .sql file $HOME/db-create.sql with following contents in both nodes:
create database mydb;
use mydb;
create table test( id int, name char(32) );
insert into test value( 1, "one" );
# mysql -uroot -p$MYSQL_ROOT_PASSWORD
MariaDB [(none)]> CREATE USER 'repuser'@'%' IDENTIFIED BY 'password@123';
Query OK, 0 rows affected (0.063 sec)
MariaDB [(none)]> GRANT REPLICATION SLAVE ON *.* TO 'repuser'@'%';
Query OK, 0 rows affected (0.049 sec)
MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.036 sec)
Before starting the mariadb server, following items should be added in the /etc/mysql/my.cnf
slow_query_log_file=/var/lib/mysql/mariadb-slow.log
expire_logs_days=14
sync_binlog=1
log_slave_updates=1
binlog_format=row
relay_log_index=/var/lib/mysql/mariadb-relaylog.index
relay_log=/var/lib/mysql/mariadb-relaylog
sync_relay_log_info=1
gtid_domain_id=1
sync_relay_log=1
relay_log_info_file=/var/lib/mysql/relay-log.info
server-id=1
bind-address=192.168.0.1
log_bin_index=/var/lib/mysql/mariadb-bin.index
event_scheduler=1
master_info_file=/var/lib/mysql/master.info
log_basename=server1
gtid_strict_mode=1
log_bin_trust_function_creators=1
sync_master_info=1
log_bin=1
Start the mariadb server in the node 192.168.0.1:
# docker run -e MYSQL_ROOT_PASSWORD=mytest@123 --net host -v /var/lib/mysql:/var/lib/mysql -v /etc/mysql/my.cnf:/etc/mysql/my.cnf -v $HOME/db-create.sql:/docker-entrypoint-initdb.d/db-create.sql -d mariadb:10.3
Before starting the slave mariadb server, following items should be added in the /etc/mysql/my.cnf
slow_query_log_file=/var/lib/mysql/mariadb-slow.log
expire_logs_days=14
sync_binlog=1
log_slave_updates=1
binlog_format=row
relay_log_index=/var/lib/mysql/mariadb-relaylog.index
relay_log=/var/lib/mysql/mariadb-relaylog
sync_relay_log_info=1
gtid_domain_id=1
sync_relay_log=1
relay_log_info_file=/var/lib/mysql/relay-log.info
server-id=2
bind-address=192.168.0.2
log_bin_index=/var/lib/mysql/mariadb-bin.index
event_scheduler=1
master_info_file=/var/lib/mysql/master.info
log_basename=server1
gtid_strict_mode=1
log_bin_trust_function_creators=1
sync_master_info=1
log_bin=1
Note: the server-id and the bind-address must be different from the master's setting
Start the slave mariadb server in the node 192.168.0.2:
# docker run -e MYSQL_ROOT_PASSWORD=mytest@123 --net host -v /var/lib/mysql:/var/lib/mysql -v /etc/mysql/my.cnf:/etc/mysql/my.cnf -v $HOME/db-create.sql:/docker-entrypoint-initdb.d/db-create.sql -d mariadb:10.3
In the master mariadb server, call mysqldump to dump all the databases:
# docker exec -it <master mariadb container-id> /bin/bash
# mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --single-transaction --all-databases --add-drop-database --events --routines --opt --add-drop-table --add-drop-trigger --master-data=2 --gtid >/var/lib/mysql/my-dump.sql
Note: the mysqldump optional parameter "--master-data" should be set to 2
Copy the /var/lib/mysql/my-dump.sql to the directory /var/lib/mysql of slave mariadb.
Go into the slave mariadb docker container to import the database:
# mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "stop slave;"
# mysql -uroot -p$MYSQL_ROOT_PASSWORD </var/lib/mysql/my-dump.sql
The /var/lib/mysql/my-dump.sql contains the gtid_slave_pos for the replication purpose.
# grep "SET GLOBAL gtid_slave_pos" /var/lib/mysql/my-dump.sql
-- SET GLOBAL gtid_slave_pos='1-2-7226';
So the gtid_slave_pos is "1-2-7226".
# mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "reset master;"
# mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "SET GLOBAL gtid_slave_pos='1-2-7226';"
# mysql -uroot -p$MYSQL_ROOT_PASSWORD
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.0.1',MASTER_PORT=3306,MASTER_USER='repuser',MASTER_PASSWORD='password@123',MASTER_USE_GTID=slave_pos;
# mysql -uroot -p$MYSQL_ROOT_PASSWORD
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.109 sec)
MariaDB [(none)]> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.2
Master_User: repuser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: 1.000003
Read_Master_Log_Pos: 782
Relay_Log_File: myserver2-relay-bin.000002
Relay_Log_Pos: 1073
Relay_Master_Log_File: 1.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 782
Relay_Log_Space: 1386
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: Slave_Pos
Gtid_IO_Pos: 1-2-7229
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Slave_DDL_Groups: 3
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.001 sec)
go to the master mariadb and insert some data to the test table.
# mysql -uroot -p$MYSQL_ROOT_PASSWORD
MariaDB [(none)]> use mydb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [mydb]> insert into test values( 2, "two");
Query OK, 1 row affected (0.081 sec)
MariaDB [mydb]> insert into test values( 3, "three");
Query OK, 1 row affected (0.095 sec)
# mysql -uroot -p$MYSQL_ROOT_PASSWORD
MariaDB [(none)]> use mydb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [mydb]> select * from test;
+------+-------+
| id | name |
+------+-------+
| 1 | one |
| 2 | two |
| 3 | three |
+------+-------+
3 rows in set (0.001 sec)
MariaDB [mydb]> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.2
Master_User: repuser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: 1.000003
Read_Master_Log_Pos: 1230
Relay_Log_File: myserver2-relay-bin.000002
Relay_Log_Pos: 1521
Relay_Master_Log_File: 1.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 1230
Relay_Log_Space: 1834
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: Slave_Pos
Gtid_IO_Pos: 1-2-7231
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Slave_DDL_Groups: 3
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 2
1 row in set (0.001 sec)
Execute in both master & slave mariadb:
# mysql -uroot -p$MYSQL_ROOT_PASSWORD
MariaDB [(none)]> GRANT SELECT ON mysql.user TO 'repuser'@'%';
Query OK, 0 rows affected (0.065 sec)
MariaDB [(none)]> GRANT SELECT ON mysql.db TO 'repuser'@'%';
Query OK, 0 rows affected (0.116 sec)
MariaDB [(none)]> GRANT SELECT ON mysql.tables_priv TO 'repuser'@'%';
Query OK, 0 rows affected (0.102 sec)
MariaDB [(none)]> GRANT SELECT ON mysql.roles_mapping TO 'repuser'@'%';
Query OK, 0 rows affected (0.103 sec)
MariaDB [(none)]> GRANT SHOW DATABASES ON *.* TO 'repuser'@'%';
Query OK, 0 rows affected (0.100 sec)
MariaDB [(none)]> GRANT SUPER ON *.* TO 'repuser'@'%';
Query OK, 0 rows affected (0.100 sec)
MariaDB [(none)]> GRANT RELOAD ON *.* TO 'repuser'@'%';
MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.038 sec)
create the $HOME/start-maxscale.sh script with following contents:
#!/bin/sh
maxkeys /var/lib/maxscale/
chown maxscale:maxscale /var/lib/maxscale/.secrets
export REP_PASSWORD=$(maxpasswd /var/lib/maxscale/ password@123)
echo $REP_PASSWORD
echo >/etc/maxscale.cnf
cat /maxscale.cnf.template | while read line; do echo $(eval echo `echo $line`) >>/etc/maxscale.cnf; done
maxscale -d -U maxscale
[maxscale]
threads=4
log_info=1
log_debug=1
[Replication-Monitor]
type=monitor
module=mariadbmon
servers=server1,server2
user=repuser
passwd=$REP_PASSWORD
replication_user=repuser
replication_password=$REP_PASSWORD
monitor_interval=2000
auto_failover=true
failover_timeout=10
auto_rejoin=true
failcount=5
master_failure_timeout=2
verify_master_failure=true
switchover_timeout=90
detect_stale_master=true
detect_stale_slave=true
[Write-Service]
type=service
router=readconnroute
router_options=master
user=repuser
passwd=$REP_PASSWORD
servers=server1,server2
[Write-Listener]
type=listener
service=Write-Service
protocol=MySQLClient
# explicitly ipv4, default is ipv6
address=0.0.0.0
port=3306
[CLI]
type=service
router=cli
[CLI-Listener]
type=listener
service=CLI
protocol=maxscaled
socket=default
[server1]
type=server
address=192.168.0.1
port=3306
protocol=MariaDBBackend
[server2]
type=server
address=192.168.0.2
port=3306
protocol=MariaDBBackend
# docker run --name maxscale -v $HOME/maxscale.cnf.template:/maxscale.cnf.template -v $HOME/start-maxscale.sh:/start-maxscale.sh -d --entrypoint /start-maxscale.sh mariadb/maxscale:2.3
# docker exec -it maxscale /bin/bash
# maxadmin
MaxScale> list servers
Servers.
-------------------+-----------------+-------+-------------+--------------------
Server | Address | Port | Connections | Status
-------------------+-----------------+-------+-------------+--------------------
server1 | 192.168.0.1 | 3306 | 0 | Master, Running
server2 | 192.168.0.2 | 3306 | 0 | Slave, Running
-------------------+-----------------+-------+-------------+--------------------