主从复制相关线程
主节点:
dump Thread: 为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events
从节点:
I/O Thread: 向Master请求二进制日志事件,并保存于中继日志中
SQL Thread: 从中继日志中读取日志事件,在本地完成重放
跟复制功能相关的文件:
范例:中继日志
[root@slave ~]#file /var/lib/mysql/mariadb-relay-bin.000001
/var/lib/mysql/mariadb-relay-bin.000001: MySQL replication log, server id 18 MySQL V5+, server version 10.3.11-MariaDB
[root@slave ~]#mysqlbinlog /var/lib/mysql/mariadb-relay-bin.000001
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#201013 17:44:14 server id 18 end_log_pos 256 CRC32 0x6fe52552 Start: binlog v 4, server v 10.3.11-MariaDB created 201013 17:44:14 at startup
ROLLBACK/*!*/;
BINLOG '
7naFXw8SAAAA/AAAAAABAAAAAAQAMTAuMy4xMS1NYXJpYURCAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADudoVfEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEEwQADQgICAoKCgFSJeVv
'/*!*/;
# at 256
#201013 17:46:22 server id 18 end_log_pos 311 CRC32 0x81d2a94c Rotate to mariadb-relay-bin.000002 pos: 4
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
复制需要考虑二进制日志事件记录格式
参考官网:
https://mariadb.com/kb/en/library/setting-up-replication/
https://dev.mysql.com/doc/refman/5.5/en/replication-configuration.html
加粗样式
主节点配置:
(1)启用二进制日志
[mysqld]
log_bin
(2)为当前节点设置一个全局唯一的ID号
[mysqld]
server-id=#
log-basename=master #可选项,设置datadir中日志名称,确保不依赖主机名
说明:
server-id的取值范围
1 to 4294967295 (>= Mariadb 10.2.2),默认值为1
0 to 4294967295 (<= Mariadb 10.2.1),默认值为0,如果节点为0,所有master都将拒绝此slave的连接
(3)查看从二进制日志的文件和位置开始进行复制
SHOW MASTER LOGS;
(4)创建有复制权限的用户帐号
GRANT REPLICATION SLAVE ON *.* TO 'repluser'@‘SHOST’ IDENTIFIED BY 'replpass';
从节点配置:
(1)启动中继日志
[mysqld]
server-id=# #为当前节点设置一个全局唯一的ID号
log-bin #此为可选项,但建议开启二进制日志
read_only=on #设置数据库只读,针对supper user无效
relay_log=relay-log #relay log的文件路径,默认值hostname-relay-bin
relay_log_index=relay-log.index #默认值hostname-relay-bin.index
(2)使用有复制权限的用户帐号连接至主服务器,并启动复制线程
CHANGE MASTER TO MASTER_HOST='masterhost',
MASTER_USER='repluser',
MASTER_PASSWORD='replpass',
MASTER_LOG_FILE='mariadb-bin.xxxxxx',
MASTER_LOG_POS=#;
START SLAVE [IO_THREAD|SQL_THREAD];
SHOW SLAVE STATUS;
#主节点
[root@centos8 ~]#hostnamectl set-hostname master.kobe.com
[root@master ~]#yum -y install mariadb-server
[root@master ~]#mkdir -p /data/mysqllogbin
[root@master ~]#chown -R mysql.mysql /data/mysqllogbin/
[root@master ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=8
bin-log=/data/mysqllogbin/mysql-bin
[root@master ~]#systemctl enable --now mariadb
[root@master ~]#mysql
#查看二进制文件和位置
MariaDB [(none)]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 28068 |
| mysql-bin.000002 | 535 |
+------------------+-----------+
2 rows in set (0.000 sec)
#创建复制用户
MariaDB [(none)]> grant replication slave on *.* to 'kobe'@'10.0.0.%' identified by 'centos';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> select user,host from mysql.user;
+------+------------------+
| user | host |
+------+------------------+
| kobe | 10.0.0.% |
| root | 127.0.0.1 |
| root | ::1 |
| root | centos8.kobe.com |
| root | localhost |
+------+------------------+
5 rows in set (0.001 sec)
#从节点
[root@centos8 ~]#hostnamectl set-hostname slave.kobe.com
[root@slave ~]#yum -y install mariadb-server
[root@slave ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
read-only
[root@slave ~]#systemctl enable --now mariadb
[root@slave ~]#mysql
MariaDB [(none)]> help change master to
CHANGE MASTER TO
MASTER_HOST='master2.mycompany.com',
MASTER_USER='replication',
MASTER_PASSWORD='bigs3cret',
MASTER_PORT=3306,
MASTER_LOG_FILE='master2-bin.001',
MASTER_LOG_POS=4;
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='kobe',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000002',
-> MASTER_LOG_POS=535;
Query OK, 0 rows affected (0.010 sec)
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.004 sec)
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 535
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 555
Relay_Master_Log_File: mysql-bin.000002
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: 535
Relay_Log_Space: 866
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: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 0
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.000 sec)
验证是否能同步数据
1)在master服务器上创建一个db1数据库
MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.001 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.000 sec)
2)在slave服务器上查看数据库是否同步到本机
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.001 sec)
范例:主服务器非新建时,主服务器运行一段时间后,新增从节点服务器
如果主节点已经运行了一段时间,且有大量数据时,如何配置并启动slave节点
#在主服务器完全备份
[root@master ~]#yum -y install mariadb-server
[root@master ~]#mkdir -p /data/mysqllogbin
[root@master ~]#chown -R mysql.mysql /data/mysqllogbin/
[root@master ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=8
bin-log=/data/mysqllogbin/mysql-bin
[root@master ~]#systemctl enable --now mariadb
[root@master ~]#mysql < hellodb_innodb.sql
[root@master ~]#mkdir /backup
[root@master ~]#mysqldump -A -F --single-transaction --master-data=1 > /backup/fullbackup_`date +%F_%T`.sql
[root@master ~]#ll /backup/
total 468
-rw-r--r-- 1 root root 479167 Oct 13 19:08 fullbackup_2020-10-13_19:08:59.sql
[root@master ~]#scp /backup/fullbackup_2020-10-13_19\:11\:35.sql 10.0.0.28:/data
#建议优化主和从服务器的性能
[root@master ~]#mysql hellodb
MariaDB [hellodb]> set global innodb_flush_log_at_trx_commit=2;
Query OK, 0 rows affected (0.000 sec)
MariaDB [hellodb]> set global sync_binlog=0;
Query OK, 0 rows affected (0.000 sec)
#将完全备份还原到新的从节点
[root@slave2 ~]#yum -y install mariadb-server
[root@slave2 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=28
read-only
[root@slave2 ~]#systemctl enable --now mariadb
#配置从节点,从完全备份的位置之后开始复制
[root@slave2 ~]#grep '^CHANGE MASTER' /data/fullbackup_2020-10-15_09\:36\:56.sql
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=385;
[root@slave2 ~]#vim /data/fullbackup_2020-10-13_19\:11\:35.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='kobe',
MASTER_PASSWORD='centos',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=385;
[root@slave2 ~]#mysql < /data/fullbackup_2020-10-15_09\:36\:56.sql
[root@slave2 ~]#mysql
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.003 sec)
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 385
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 555
Relay_Master_Log_File: mysql-bin.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: 385
Relay_Log_Space: 866
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: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 0
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.000 sec)
验证数据是否能同步到新的slave2服务器上
1)在master服务器上新建数据库db2
MariaDB [(none)]> create database db2;
Query OK, 1 row affected (0.002 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
6 rows in set (0.001 sec)
2)在slave2上查看db2是否同步到本机上
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
6 rows in set (0.001 sec)
read-only=ON
#注意:此限制对拥有SUPER权限的用户均无效
注意:以下命令会阻止所有用户,包括主服务器复制的更新
FLUSH TABLES WITH READ LOCK;
注意:以下都需要先STOP SLAVE
RESET SLAVE #从服务器清除master.info,relay-log.info,开始新的relay log
RESET SLAVE ALL #清除所有从服务器上设置的主服务器同步信息,如HOST,PORT,USER和PASSWORD等
可以在从服务器忽略几个主服务器的复制事件,此为global变量,或指定跳过事件的ID
注意:CentOS 8.1以上版本上主从节点同时建同名的库和表不会冲突,建主键记录会产生冲突
#系统变量,指定跳过复制事件的个数
SET GLOBAL sql_slave_skip_counter = N
#服务器选项,只读系统变量,指定跳过事件的ID
[mysqld]
slave_skip_errors=1007|ALL
范例:复制冲突的解决
#先在slave上创建库,在master上创建同名的库,会出现复制冲突,而创建表不会
#如果添加相同的主键记录都会冲突
以下两个系统都是centos8
这里以slave2 10.0.0.28为例,在salve2上创建一个db3和test表,再在master 10.0.0.8上创建db3和test表
1)在slave2上
MariaDB [(none)]> create database db3;
Query OK, 1 row affected (0.000 sec)
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 512
Relay_Log_File: mariadb-relay-bin.000006
Relay_Log_Pos: 811
Relay_Master_Log_File: mysql-bin.000004
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: 512
Relay_Log_Space: 1169
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: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 31
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 6
1 row in set (0.001 sec)
2)在master上
MariaDB [(none)]> create database db3;
Query OK, 1 row affected (0.001 sec)
3)在slave上
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 920
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 963
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1007
Last_Error: Error 'Can't create database 'db4'; database exists' on query. Default database: 'db4'. Query: 'create database db4'
Skip_Counter: 0
Exec_Master_Log_Pos: 793
Relay_Log_Space: 1401
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1007 #错误编码
Last_SQL_Error: Error 'Can't create database 'db4'; database exists' on query. Default database: 'db4'. Query: 'create database db4'
Replicate_Ignore_Server_Ids:
Master_Server_Id: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Slave_DDL_Groups: 4
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.001 sec)
#方法1
MariaDB [(none)]> stop slave;
MariaDB [(none)]> set global sql_slave_skip_counter=1;
MariaDB [(none)]> start slave;
#方法2
[root@slave ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
slave_skip_errors=1007|ALL #1007是错误的编码,也可以写成ALL
[root@slave1 ~]#systemctl restart mariadb
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 920
Relay_Log_File: mariadb-relay-bin.000008
Relay_Log_Pos: 555
Relay_Master_Log_File: mysql-bin.000004
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: 920
Relay_Log_Space: 866
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: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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)
START SLAVE [thread_types]
START SLAVE [SQL_THREAD] UNTIL
MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
START SLAVE [SQL_THREAD] UNTIL
RELAY_LOG_FILE = 'log_name',RELAY_LOG_POS = log_pos
thread_types:
[thread_type [, thread_type] ... ]
thread_type: IO_THREAD | SQL_THREAD
参考:https://mariadb.com/kb/en/library/server-system-variables/
在master节点启用参数:
sync_binlog=1 每次写后立即同步二进制日志到磁盘,性能差
#如果用到的为InnoDB存储引擎:
innodb_flush_log_at_trx_commit=1 #每次事务提交立即同步日志写磁盘
innodb_support_xa=ON #分布式事务MariaDB 10.3.0废除
sync_master_info=# #次事件后master.info同步到磁盘
在slave节点启用服务器选项:
skip-slave-start=ON #不自动启动slave
在slave节点启用参数:
sync_relay_log=# #次写后同步relay log到磁盘
sync_relay_log_info=# #次事务后同步relay-log.info到磁盘
模拟主节点master宕机
[root@master ~]#mysql hellodb < testlog.sql
[root@master ~]#mysql hellodb
MariaDB [hellodb]> call sp_testlog;
[root@master ~]#killall mysqld
#找到那个从节点的数据库是最新的,让它成为新master
1)slave1上查看Read_Master_Log_Pos的位置
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Reconnecting after a failed master event read
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000007
Read_Master_Log_Pos: 933850 #查看的值
Relay_Log_File: mariadb-relay-bin.000003
Relay_Log_Pos: 934107
Relay_Master_Log_File: mysql-bin.000007
Slave_IO_Running: Connecting
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: 933808
Relay_Log_Space: 4988571
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 2003
Last_IO_Error: error reconnecting to master '[email protected]:3306' - retry-time: 60 maximum-retries: 86400 message: Can't connect to MySQL server on '10.0.0.8' (111 "Connection refused")
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 0
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 18317
1 row in set (0.001 sec)
2)slave2上查看Read_Master_Log_Pos的位置
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Reconnecting after a failed master event read
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000007
Read_Master_Log_Pos: 933808 #查看的值
Relay_Log_File: mariadb-relay-bin.000011
Relay_Log_Pos: 934107
Relay_Master_Log_File: mysql-bin.000007
Slave_IO_Running: Connecting
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: 933808
Relay_Log_Space: 935265
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 2003
Last_IO_Error: error reconnecting to master '[email protected]:3306' - retry-time: 60 maximum-retries: 86400 message: Can't connect to MySQL server on '10.0.0.8' (111 "Connection refused")
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 10
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 140441
1 row in set (0.000 sec)
3)对比发现slave1 从节点上的数据库是最新的,即让它成为新master
#在新master上修改配置文件(即slave1),关闭read-only配置
[root@slave ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
read-only=OFF
log-bin=/data/mysqllogbin/mysql-bin
[root@slave ~]#mkdir -p /data/mysqllogbin
[root@slave ~]#chown -R mysql.mysql /data/mysqllogbin/
[root@slave ~]#systemctl restart mariadb.service
#清除旧的master复制信息
MariaDB [(none)]> set global read_only=0;
MariaDB [(none)]> stop slave;
MariaDB [(none)]> reset slave all;
#分析旧的master 的二进制日志,将未同步到至新master的二进制日志导出来,恢复到新master,尽可能恢复数据
[root@master ~]#mysqlbinlog /data/mysqllogbin/mysql-bin.000007 > old.sql
[root@master ~]#vim old.sql
[root@master ~]#cat old.sql
# at 933850
#201015 12:29:21 server id 8 end_log_pos 933882 CRC32 0x76d04b97 Intvar
SET INSERT_ID=40442/*!*/;
# at 933882
#201015 12:29:21 server id 8 end_log_pos 934049 CRC32 0x6b3c044e Query thread_id=12 exec_time=0 error_code=0
SET TIMESTAMP=1602736161/*!*/;
insert into testlog(name,age) values (concat('wang', NAME_CONST('i',3441)), NAME_CONST('i',3441))
/*!*/;
# at 934049
#201015 12:29:21 server id 8 end_log_pos 934080 CRC32 0xc3f342cb Xid = 10357
COMMIT/*!*/;
# at 934080
#201015 12:29:21 server id 8 end_log_pos 934122 CRC32 0x2189b20c GTID 0-8-140533 trans
/*!100001 SET @@session.gtid_seq_no=140533*//*!*/;
BEGIN
/*!*/;
# at 934122
#201015 12:29:21 server id 8 end_log_pos 934154 CRC32 0xd35587db Intvar
SET INSERT_ID=40443/*!*/;
# at 934154
#201015 12:29:21 server id 8 end_log_pos 934321 CRC32 0x2a85972a Query thread_id=12 exec_time=0 error_code=0
SET TIMESTAMP=1602736161/*!*/;
insert into testlog(name,age) values (concat('wang', NAME_CONST('i',3442)), NAME_CONST('i',3442))
/*!*/;
# at 934321
#201015 12:29:21 server id 8 end_log_pos 934352 CRC32 0xe3d2b2f3 Xid = 10360
COMMIT/*!*/;
# at 934352
#201015 12:29:21 server id 8 end_log_pos 934375 CRC32 0xa4dd2e09 Stop
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
#将old.sql 复制到新master上
[root@master ~]#scp old.sql 10.0.0.18:
#在新master上恢复数据
[root@slave ~]#mysql hellodb
MariaDB [hellodb]> source /root/old.sql;
#在新master上完全备份
[root@slave ~]#mysqldump -A -F --single-transaction --master-data=1 > /data/backup_`date +%F_%T`.sql
#将完全备份的文件拷贝到其它所有的从服务器上,由于该实验只有从服务slave2了,所以只拷贝一次
[root@slave ~]#scp /data/backup_2020-10-15_10\:48\:57.sql 10.0.0.28:/data
#其它所有 slave 重新还原数据库,指向新的master
[root@slave2 ~]#vim /data/fullbackup.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.18',
MASTER_USER='kobe',
MASTER_PASSWORD='centos',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000002',
MASTER_LOG_POS=342;
[root@slave2 ~]#mysql hellodb
MariaDB [mysql]> stop slave;
MariaDB [mysql]> reset slave all;
MariaDB [mysql]> set sql_log_bin=0;
MariaDB [mysql]> source /data/fullbackup.sql
MariaDB [mysql]> set sql_log_bin=1;
MariaDB [mysql]> start slave;
#在从服务器上验证:
MariaDB [mysql]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.18
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 385
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 598
Relay_Master_Log_File: mysql-bin.000002
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: 385
Relay_Log_Space: 909
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: 18
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 10
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 140441
1 row in set (0.001 sec)
MariaDB [hellodb]> select count(*) from testlog;
+----------+
| count(*) |
+----------+
| 40443 |
+----------+
1 row in set (0.010 sec)
在新master上创建新库db2
MariaDB [hellodb]> create database db2;
Query OK, 1 row affected (0.001 sec)
在从服务器上查看是否同步
MariaDB [hellodb]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
6 rows in set (0.000 sec)
需要在中间的从服务器启用以下配置,实现中间slave节点能将master的二进制日志在本机进行数据库更新,并且同时更新本机的二进制,从而实现级联复制
[mysqld]
server-id=18
log_bin
log_slave_updates
read-only
#让10.0.0.8充当master
#让10.0.0.18充当slave1
#让10.0.0.28充当slave2
#在master上
[root@centos8 ~]#hostnamectl set-hostname master.kobe.com
[root@master ~]#yum -y install mariadb-server
[root@master ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=8
log-bin=/data/mysqllogbin/mysql-bin
[root@master ~]#mkdir -p /data/mysqllogbin
[root@master ~]#chown -R mysql.mysql /data/mysqllogbin/
[root@master ~]#systemctl enable --now mariadb
[root@master ~]#mysql < hellodb_innodb.sql
[root@master ~]#mysql
MariaDB [(none)]> grant replication slave on *.* to 'kobe'@'10.0.0.%' identified by 'centos';
[root@master ~]#mysqldump -A -F --single-transaction --master-data=1 > fullbackup.sql
[root@master ~]#scp fullbackup.sql 10.0.0.18:
[root@master ~]#scp fullbackup.sql 10.0.0.28:
#在从节点slave1实现
[root@centos8 ~]#hostnamectl set-hostname slave1.kobe.com
[root@slave1 ~]#yum -y install mariadb-server
[root@slave1 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
log-bin=/data/mysqllogbin/mysql-bin
read-only
[root@slave1 ~]#mkdir -p /data/mysqllogbin
[root@slave1 ~]#chown -R mysql.mysql /data/mysqllogbin/
[root@slave1 ~]#systemctl enable --now mariadb
#在slave1上还原数据库
[root@slave1 ~]#vim fullbackup.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='kobe',
MASTER_PASSWORD='centos',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=385;
[root@slave1 ~]#mysql
MariaDB [(none)]> set sql_log_bin=0;
MariaDB [(none)]> source /root/fullbackup.sql;
MariaDB [mysql]> set sql_log_bin=1;
MariaDB [mysql]> start slave;
#在其它从服务器节点上,这里是在第三个节点slave2上实现
[root@centos8 ~]#hostnamectl set-hostname slave2.kobe.com
[root@slave2 ~]#yum -y install mariadb-server
[root@slave2 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=28
read-only
[root@slave2 ~]#systemctl enable --now mariadb
[root@slave2 ~]#vim fullbackup.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='kobe',
MASTER_PASSWORD='centos',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=385;
[root@slave2 ~]#mysql
MariaDB [mysql]> set sql_log_bin=0;
MariaDB [(none)]> source /root/fullbackup.sql;
MariaDB [mysql]> set sql_log_bin=1;
MariaDB [mysql]> start slave;
#在master上创建库db1
MariaDB [(none)]> create database db1;
#此时其它从节点应都同步到新数据
#在slave1上,以slave1为例
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
5 rows in set (0.001 sec)
#在slave2上drop database db1
MariaDB [(none)]> drop database db1;
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.001 sec)
#在级联节点slave1上修改配置
[root@slave1 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
log-bin=/data/mysqllogbin/mysql-bin
read-only
log_slave_updates
[root@slave1 ~]#systemctl restart mariadb
#在slave1上实现完全备份
[root@slave1 ~]#mysqldump -A -F --single-transaction --master-data=1 > allbackup.sql
[root@slave1 ~]#scp allbackup.sql 10.0.0.28:
#在其它从节点上,这里是从节点上slave2上
[root@slave2 ~]#vim allbackup.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.18', #级联节点的IP
MASTER_USER='kobe',
MASTER_PASSWORD='centos',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=385;
[root@slave2 ~]#mysql
MariaDB [(none)]> stop slave;
MariaDB [(none)]> reset slave all;
MariaDB [(none)]> set sql_log_bin=0;
MariaDB [(none)]> source /root/allbackup.sql;
MariaDB [mysql]> set sql_log_bin=1;
MariaDB [mysql]> start slave;
MariaDB [mysql]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.18
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 385
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 555
Relay_Master_Log_File: mysql-bin.000004
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: 385
Relay_Log_Space: 866
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: 18
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 1
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.000 sec)
#验证
#在master上创建库db2
MariaDB [(none)]> create database db2;
#在slave2上查看
MariaDB [mysql]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
6 rows in set (0.001 sec)
主主复制:两个节点,都可以更新数据,并且互为主从
容易产生的问题:数据不一致;因此慎用
考虑要点:自动增长id
配置一个节点使用奇数id
auto_increment_offset=1 #开始点
auto_increment_increment=2 #增长幅度
另一个节点使用偶数id
auto_increment_offset=2
auto_increment_increment=2
主主复制的配置步骤:
(1)各节点使用一个唯一server-id
(2)都启动binary log和relay log
(3)创建拥有复制权限的用户账号
(4)定义自动增长id字段的数值范围各为奇偶
(5)均把对方指定为主节点,并启动复制线程
范例:实现两个节点的主主复制模型
#在第一个master节点上实现
[root@centos8 ~]#hostnamectl set-hostname master1.kobe.com
[root@master1 ~]#yum -y install mariadb-server
[root@master1 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=8
log-bin
auto_increment_offset=1 #开始点
auto_increment_increment=2 #增长幅度
[root@master1 ~]#systemctl enable --now mariadb
[root@master1 ~]#mysql
MariaDB [(none)]> grant replication slave on *.* to kobe@'10.0.0.%' identified by 'centos';
#查看二进制位置,给master2使用
MariaDB [(none)]> show master logs;
+--------------------+-----------+
| Log_name | File_size |
+--------------------+-----------+
| mariadb-bin.000001 | 28297 |
| mariadb-bin.000002 | 542 |
+--------------------+-----------+
2 rows in set (0.000 sec)
#在第二个节点master2上实现
[root@centos8 ~]#hostnamectl set-hostname master2.kobe.com
[root@master2 ~]#yum -y install mariadb-server
[root@master2 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
log-bin
auto_increment_offset=2 #开始点
auto_increment_increment=2 #增长幅度
[root@master2 ~]#systemctl enable --now mariadb
[root@master2 ~]#mysql
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='kobe',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000002',
-> MASTER_LOG_POS=542;
Query OK, 0 rows affected (0.008 sec)
MariaDB [(none)]> start slave;
#查看二进制位置,给master1使用
MariaDB [(none)]> show master logs;
+--------------------+-----------+
| Log_name | File_size |
+--------------------+-----------+
| mariadb-bin.000001 | 28297 |
| mariadb-bin.000002 | 344 |
+--------------------+-----------+
2 rows in set (0.001 sec)
#在master1节点上实现
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.18',
-> MASTER_USER='kobe',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000002',
-> MASTER_LOG_POS=344;
Query OK, 0 rows affected (0.006 sec)
MariaDB [(none)]> start slave;
MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.001 sec)
MariaDB [(none)]> use db1
Database changed
MariaDB [db1]> create table test(id int auto_increment primary key,name char(10));
Query OK, 0 rows affected (0.012 sec)
#两个节点分别插入数据
#在第一个节点上执行
MariaDB [db1]> insert test(name) value('kobe');
Query OK, 1 row affected (0.002 sec)
#在第二个节点上执行
MariaDB [(none)]> use db1
MariaDB [db1]> insert test(name) value('bryant');
Query OK, 1 row affected (0.002 sec)
#查看数据
MariaDB [db1]> select * from test;
+----+--------+
| id | name |
+----+--------+
| 1 | kobe |
| 2 | bryant |
+----+--------+
2 rows in set (0.001 sec)
#两个节点同时插入数据
#使用Xshell中的查看-->撰写-->撰写栏,使用发送文本到当前Xshell窗口的全部会话
MariaDB [db1]> select * from test;
+----+----------+
| id | name |
+----+----------+
| 1 | kobe |
| 2 | bryant |
| 3 | test |
| 4 | testuser |
| 5 | testuser |
+----+----------+
5 rows in set (0.001 sec)
#两个节点同时创建数据库,发生复制冲突
MariaDB [db1]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000002
Read_Master_Log_Pos: 1612
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 1495
Relay_Master_Log_File: mariadb-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1007
Last_Error: Error 'Can't create database 'db2'; database exists' on query. Default database: 'db2'. Query: 'create database db2'
Skip_Counter: 0
Exec_Master_Log_Pos: 1480
Relay_Log_Space: 1938
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1007
Last_SQL_Error: Error 'Can't create database 'db2'; database exists' on query. Default database: 'db2'. Query: 'create database db2'
Replicate_Ignore_Server_Ids:
Master_Server_Id: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Slave_DDL_Groups: 3
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 3
1 row in set (0.001 sec)
默认情况下,MySQL的复制功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发给从库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失
半同步复制实现:
官方文档:https://mariadb.com/kb/en/library/semisynchronous-replication/
范例:CentOS 8在Mariadb 10.3.11 上实现半同步复制
#首先搭建主从复制架构,搭建步骤参考上面的笔记
三台机器
#让10.0.0.8充当master
#让10.0.0.18充当slave1
#让10.0.0.28充当slave2
#在搭建好主从架构后,做半同步复制
#在master上实现,启用半同步功能
[root@master ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=8
log-bin
plugin_load_add = semisync_master
rpl_semi_sync_master_enabled=ON
rpl_semi_sync_master_timeout=3000 #设置3秒内无法同步,也将返回成功信息给客户端
[root@master ~]#systemctl restart mariadb
[root@master ~]#mysql
MariaDB [(none)]> show global variables like '%semi%';
+---------------------------------------+--------------+
| Variable_name | Value |
+---------------------------------------+--------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 3000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_COMMIT |
| rpl_semi_sync_slave_delay_master | OFF |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_kill_conn_timeout | 5 |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------------+--------------+
9 rows in set (0.003 sec)
MariaDB [(none)]> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_get_ack | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_request_ack | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
| Rpl_semi_sync_slave_send_ack | 0 |
| Rpl_semi_sync_slave_status | OFF |
+--------------------------------------------+-------+
18 rows in set (0.002 sec)
#在其它所有从节点上都实现,启用半同步功能
1)在slave1上实现
[root@slave1 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
plugin_load_add = semisync_slave
rpl_semi_sync_slave_enabled=ON
[root@slave1 ~]#systemctl restart mariadb
[root@slave1 ~]#mysql
MariaDB [(none)]> show global variables like '%semi%';
+---------------------------------------+--------------+
| Variable_name | Value |
+---------------------------------------+--------------+
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_COMMIT |
| rpl_semi_sync_slave_delay_master | OFF |
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_kill_conn_timeout | 5 |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------------+--------------+
9 rows in set (0.003 sec)
MariaDB [(none)]> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_get_ack | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_request_ack | 0 |
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
| Rpl_semi_sync_slave_send_ack | 0 |
| Rpl_semi_sync_slave_status | ON |
+--------------------------------------------+-------+
18 rows in set (0.003 sec)
2)在slave2上实现
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=28
plugin_load_add = semisync_slave
rpl_semi_sync_slave_enabled=ON
[root@centos8 ~]#systemctl restart mariadb
MariaDB [(none)]> show global variables like '%semi%';
+---------------------------------------+--------------+
| Variable_name | Value |
+---------------------------------------+--------------+
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_COMMIT |
| rpl_semi_sync_slave_delay_master | OFF |
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_kill_conn_timeout | 5 |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------------+--------------+
9 rows in set (0.002 sec)
MariaDB [(none)]> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_get_ack | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_request_ack | 0 |
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
| Rpl_semi_sync_slave_send_ack | 0 |
| Rpl_semi_sync_slave_status | ON |
+--------------------------------------------+-------+
18 rows in set (0.002 sec)
#在master上实现
MariaDB [(none)]> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 | #两个从节点
| Rpl_semi_sync_master_get_ack | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_request_ack | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
| Rpl_semi_sync_slave_send_ack | 0 |
| Rpl_semi_sync_slave_status | OFF |
+--------------------------------------------+-------+
18 rows in set (0.001 sec)
#测试
#在master上创建数据库db1,立即成功
MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.004 sec)
#在所有slave节点上,停止复制线程
1)在slave1上
MariaDB [(none)]> stop slave;
Query OK, 0 rows affected (0.008 sec)
2)在slave2上
MariaDB [(none)]> stop slave;
Query OK, 0 rows affected (0.008 sec)
#在master上创建数据库db2,等待3s才能成功
MariaDB [(none)]> create database db2;
Query OK, 1 row affected (3.002 sec)
#在任意一个slave节点实现,恢复复制线程
这里以slave2为例
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.003 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
6 rows in set (0.001 sec)
#在master上,创建数据库db3,立即成功
MariaDB [(none)]> create database db3;
Query OK, 1 row affected (0.003 sec)
#在slave2上查看
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| db3 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
7 rows in set (0.001 sec)
#在slave1上查看
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
5 rows in set (0.001 sec)
#在所有从节点停止同步线程,在主节点可以看到以下日志信息
MariaDB [(none)]> stop slave;
[root@centos8 ~]#tail /var/log/mariadb/mariadb.log
2020-10-15 17:32:17 14 [Note] Start binlog_dump to slave_server(28), pos(mariadb-bin.000005, 344)
2020-10-15 17:32:17 14 [Note] Start semi-sync binlog_dump to slave (server_id: 28), pos(mariadb-bin.000005, 344)
2020-10-15 17:36:54 13 [Note] Stop semi-sync binlog_dump to slave (server_id: 18)
2020-10-15 17:37:39 14 [Note] Stop semi-sync binlog_dump to slave (server_id: 28)
2020-10-15 17:39:02 10 [Warning] Timeout waiting for reply of binlog (file: mariadb-bin.000005, pos: 598), semi-sync up to file mariadb-bin.000005, position 471.
2020-10-15 17:39:02 10 [Note] Semi-sync replication switched OFF.
2020-10-15 17:40:31 17 [Note] Start binlog_dump to slave_server(28), pos(mariadb-bin.000005, 471)
2020-10-15 17:40:31 17 [Note] Start semi-sync binlog_dump to slave (server_id: 28), pos(mariadb-bin.000005, 471)
2020-10-15 17:40:31 6 [Note] Semi-sync replication switched ON with slave (server_id: 28) at (mariadb-bin.000005, 598)
2020-10-15 17:46:13 17 [Note] Stop semi-sync binlog_dump to slave (server_id: 28)
范例:CentOS 7实现Mariadb 5.5.65的半同步复制
#主服务器配置:
MariaDB [(none)]>INSTALL PLUGIN rpl_semi_sync_master SONAME
'semisync_master.so';
MariaDB [(none)]>UNINSTALL PLUGIN rpl_semi_sync_master ;
MariaDB [(none)]>SHOW PLUGINS; #查看插件
MariaDB [(none)]>SET GLOBAL rpl_semi_sync_master_enabled=1;
MariaDB [(none)]>SET GLOBAL rpl_semi_sync_master_timeout = 1000; #超时长1s,默认值为10s
MariaDB [(none)]>SHOW GLOBAL VARIABLES LIKE '%semi%';
MariaDB [(none)]>SHOW GLOBAL STATUS LIKE '%semi%';
#从服务器配置:
MariaDB [(none)]>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
MariaDB [(none)]>SET GLOBAL rpl_semi_sync_slave_enabled=1;
#mariadb-10.3版以后
#主服务器配置:
[mysqld]
plugin_load_add = semisync_master
#从服务器配置:
[mysqld]
plugin_load_add = semisync_slave
在默认的主从复制过程或远程连接到MySQL/MariaDB所有的链接通信中的数据都是明文的,外网访问数据或者复制,存在安全隐患
通过SSL/TLS加密的方式进行复制的方法,来进一步提高数据的安全性
官网文档:https://mariadb.com/kb/en/library/replication-with-secure-connections/
实现MySQL复制加密
1.生成CA及master和slave的证书
[root@centos8 ~]#mkdir /etc/my.cnf.d/ssl/
[root@centos8 ~]#cd /etc/my.cnf.d/ssl/
[root@centos8 ssl]#openssl genrsa 2048 > cakey.pem
Generating RSA private key, 2048 bit long modulus (2 primes)
...+++++
..........................+++++
e is 65537 (0x010001)
[root@centos8 ssl]#openssl req -new -x509 -key cakey.pem --out cacert.pem -days
3650
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:magedu
Organizational Unit Name (eg, section) []:opt
Common Name (eg, your name or your server's hostname) []:ca.magedu.org
Email Address []:
[root@centos8 ssl]#ls
cacert.pem cakey.pem
[root@centos8 ssl]#openssl req -newkey rsa:2048 -nodes -keyout master.key >
master.csr
Generating a RSA private key
..+++++
................................................................................
.................+++++
writing new private key to 'master.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:magedu
Organizational Unit Name (eg, section) []:opt
Common Name (eg, your name or your server's hostname) []:ca.magedu.org
Email Address []:
[root@centos8 ssl]#ls
cacert.pem cakey.pem
[root@centos8 ssl]#openssl req -newkey rsa:2048 -nodes -keyout master.key >
master.csr
Generating a RSA private key
..+++++
................................................................................
.................+++++
writing new private key to 'master.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:magedu
Organizational Unit Name (eg, section) []:opt
Common Name (eg, your name or your server's hostname) []:master.magedu.org
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@centos8 data]#ls
cacert.pem cakey.pem master.csr master.key
[root@centos8 ssl]#openssl x509 -req -in master.csr -CA cacert.pem -CAkey
cakey.pem --set_serial 01 > master.crt
Signature ok
subject=C = CN, ST = beijing, L = beijing, O = magedu, OU = opt, CN =
master.magedu.org
Getting CA Private Key
[root@centos8 ssl]#ls
cacert.pem cakey.pem master.crt master.csr master.key
[root@centos8 ssl]#openssl req -newkey rsa:2048 -nodes -keyout slave.key >
slave.csr
Generating a RSA private key
.................................+++++
...............................................+++++
writing new private key to 'slave.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:magedu
Organizational Unit Name (eg, section) []:opt
Common Name (eg, your name or your server's hostname) []:slave.magedu.org
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@centos8 ssl]#
[root@centos8 ssl]#openssl x509 -req -in slave.csr -CA cacert.pem -CAkey
cakey.pem --set_serial 02 > slave.crt
Signature ok
subject=C = CN, ST = beijing, L = beijing, O = magedu, OU = opt, CN =
slave.magedu.org
Getting CA Private Key
[root@centos8 ssl]#ls
cacert.pem cakey.pem master.crt master.csr master.key slave.crt slave.csr
slave.key
#修改权限
[root@centos8 ~]#chown -R mysql.mysql /etc/my.cnf.d/ssl/
#如果上面没修改权限,会出现ssl无法启动和下面日志错误
MariaDB [(none)]> show variables like '%ssl%';
+---------------------+----------------------------------+
| Variable_name | Value |
+---------------------+----------------------------------+
| have_openssl | YES |
| have_ssl | DISABLED #无法启用,正常启用为YES |
| ssl_ca | /etc/my.cnf.d/ssl/cacert.pem |
| ssl_capath | |
| ssl_cert | /etc/my.cnf.d/ssl/master.crt |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | /etc/my.cnf.d/ssl/master.key |
| version_ssl_library | OpenSSL 1.1.1c FIPS 28 May 2019 |
+---------------------+----------------------------------+
10 rows in set (0.001 sec)
[root@centos8 ~]#cat /var/log/mariadb/mariadb.log
2020-10-12 17:55:35 0 [Warning] Failed to setup SSL
2020-10-12 17:55:35 0 [Warning] SSL error: Unable to get private key
2020-10-12 17:55:35 0 [Warning] SSL error: error:0200100D:system
library:fopen:Permission denied
2020-10-12 17:55:35 0 [Warning] SSL error: error:20074002:BIO
routines:file_ctrl:system lib
2020-10-12 17:55:35 0 [Warning] SSL error: error:140B0002:SSL
routines:SSL_CTX_use_PrivateKey_file:system lib
2.主服务器开启 SSL,配置证书和私钥路径
[root@centos8 ~]#vim /etc/my.cnf
[mysqld]
log-bin
server_id=1
ssl
ssl-ca=/etc/my.cnf.d/ssl/cacert.pem
ssl-cert=/etc/my.cnf.d/ssl/master.crt
ssl-key=/etc/my.cnf.d/ssl/master.key
[root@centos8 ~]#mysql
MariaDB [(none)]> show variables like '%ssl%';
+---------------------+----------------------------------+
| Variable_name | Value |
+---------------------+----------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /etc/my.cnf.d/ssl/cacert.pem |
| ssl_capath | |
| ssl_cert | /etc/my.cnf.d/ssl/master.crt |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | /etc/my.cnf.d/ssl/master.key |
| version_ssl_library | OpenSSL 1.1.1c FIPS 28 May 2019 |
+---------------------+----------------------------------+
10 rows in set (0.001 sec)
3.创建一个要求必须使用 SSL 连接的复制账号
GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'10.0.0.%' IDENTIFIED BY 'magedu'
REQUIRE SSL;
4.从服务器slave上使用CHANGER MASTER TO 命令时指明ssl相关选项
[root@centos8 ~]#mysql -urepluser -pmagedu -h10.0.0.8
ERROR 1045 (28000): Access denied for user 'repluser'@'10.0.0.18' (using
password: YES)
[root@centos8 ~]#mysql -urepluser -pmagedu -h10.0.0.8 --sslca=/
etc/my.cnf.d/ssl/cacert.pem --ssl-cert=/etc/my.cnf.d/ssl/slave.crt --sslkey=/
etc/my.cnf.d/ssl/slave.key
MariaDB [(none)]>
[root@centos8 ~]#chown -R mysql.mysql /etc/my.cnf.d/ssl/
#可选方式1
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=2
ssl
ssl-ca=/etc/my.cnf.d/ssl/cacert.pem
ssl-cert=/etc/my.cnf.d/ssl/slave.crt
ssl-key=/etc/my.cnf.d/ssl/slave.key
MariaDB [(none)]>CHANGE MASTER TO
MASTER_HOST='MASTERIP',
MASTER_USER='repluser',
MASTER_PASSWORD='magedu',
MASTER_LOG_FILE='mariadb-bin.000001',
MASTER_LOG_POS=245,
MASTER_SSL=1;
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000009
Read_Master_Log_Pos: 944
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 811
Relay_Master_Log_File: mariadb-bin.000009
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: 944
Relay_Log_Space: 1122
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: Yes
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: 8
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 2
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.000 sec)
#可选方式2
#需修改配置文件,执行下面命令即可
MariaDB [(none)]>CHANGE MASTER TO
MASTER_HOST='MASTERIP',
MASTER_USER='repluser',
MASTER_PASSWORD='magedu',
MASTER_LOG_FILE='mariadb-bin.000001',
MASTER_LOG_POS=245,
MASTER_SSL=1,
MASTER_SSL_CA = '/etc/my.cnf.d/ssl/cacert.pem',
MASTER_SSL_CERT = '/etc/my.cnf.d/ssl/slave.crt',
MASTER_SSL_KEY = '/etc/my.cnf.d/ssl/slave.key';
MariaDB [(none)]>start slave;
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000009
Read_Master_Log_Pos: 944
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 811
Relay_Master_Log_File: mariadb-bin.000009
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: 944
Relay_Log_Space: 1122
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: Yes
Master_SSL_CA_File: /etc/my.cnf.d/ssl/cacert.pem
Master_SSL_CA_Path:
Master_SSL_Cert: /etc/my.cnf.d/ssl/slave2.crt
Master_SSL_Cipher:
Master_SSL_Key: /etc/my.cnf.d/ssl/slave2.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: 8
Master_SSL_Crl: /etc/my.cnf.d/ssl/cacert.pem
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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.000 sec)
GTID复制:(Global Transaction ID 全局事务标识符) MySQL 5.6版本开始支持,GTID复制不像传统的复制方式(异步复制、半同步复制)需要找到binlog文件名和POS点,只需知道master的IP、端口、账号、密码即可。开启GTID以后,执行change master to master_auto_position=1即可,它会自动寻找到相应的位置开始同步
GTID 架构
GTID =server_uuid:transaction_id,在一组复制中,全局唯一
server_uuid 来源于/var/lib/mysql/auto.cnf
GTID服务器相关选项
gtid_mode #gtid模式
enforce_gtid_consistency #保证GTID安全的参数
GTID配置示例
1.主服务器
vim /etc/my.cnf
server-id=1
log-bin=mysql-bin #可选
gtid_mode=ON
enforce_gtid_consistency
mysql> grant replication slave on *.* to 'repluser'@'10.0.0.%' identified by
'magedu';
2.从服务器
vim /etc/my.cnf
server-id=2
gtid_mode=ON
enforce_gtid_consistency
mysql>CHANGE MASTER TO MASTER_HOST='10.0.0.100',
MASTER_USER='repluser',
MASTER_PASSWORD='magedu',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1;
mysql>start slave;
范例:实现MySQL 5.7 主从架构的GTID
#在主服务器master上
[root@master ~]#ll
total 644560
-rw-r--r-- 1 root root 1947 Oct 15 18:48 1.sh
-rw-r--r-- 1 root root 660017902 Sep 21 14:22 mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
[root@master ~]#cat 1.sh
# mysql-5.7.30 Generic URL:https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
# mysql-8.0.20 Generic URL:https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz
URL="https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz"
PACK=mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
DIR=mysql-5.7.30-linux-glibc2.12-x86_64
DIR1=/var/lib/mysqllogbin
yum -y install ncurses-compat-libs-6.1-7.20180224.el8.x86_64 &> /dev/null
groupadd -r mysql
useradd -r -g mysql -s /sbin/nologin mysql
#wegt $URL
tar xf $PACK -C /usr/local
cd /usr/local
ln -s $DIR mysql
cd mysql
chown -R root.root ./*
echo "PATH=/usr/local/mysql/bin:$PATH" > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
ln -s /usr/local/mysql/bin/* /usr/bin
PASS1="centos"
cat > /etc/my.cnf <\\_
EOF
mysqld --initialize --user=mysql --datadir=/data/mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
service mysqld start
PASS2=`awk '/temporary password/{print $NF}' /data/mysql/mysql.log`
PASS3="centos"
mysqladmin -uroot -p"${PASS2}" password ${PASS3}
SID=`hostname -I | awk -F. '{print $4}'`
sed -ri "s#^(\[mysqld\])#\1\nserver-id=${SID}\nlog_bin=/var/lib/mysqllogbin/mysql-bin#" /etc/my.cnf
[ -d $DIR1 ] || mkdir -p $DIR1
chown -R mysql.mysql $DIR1
service mysqld restart
[root@master ~]#vim /etc/my.cnf
[mysqld]
server-id=8
log_bin=/var/lib/mysqllogbin/mysql-bin
gtid_mode=ON
enforce_gtid_consistency
[root@master ~]#service mysqld restart
[root@master ~]#mysql
(root@localhost) [(none)]> grant replication slave on *.* to kobe@'10.0.0.%' identified by 'centos';
Query OK, 0 rows affected, 1 warning (0.00 sec)
(root@localhost) [(none)]> select user,host from mysql.user;
+---------------+-----------+
| user | host |
+---------------+-----------+
| kobe | 10.0.0.% |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+-----------+
4 rows in set (0.00 sec)
#从服务器slave1上
使用脚本安装MySQL 5.7,参考如上脚本
[root@slave1 ~]#vim /etc/my.cnf
[mysqld]
server-id=18
log_bin=/var/lib/mysqllogbin/mysql-bin
gtid_mode=ON
enforce_gtid_consistency
[root@slave1 ~]#service mysqld restart
[root@slave1 ~]#mysql
(root@localhost) [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='kobe',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
(root@localhost) [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)
(root@localhost) [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 444
Relay_Log_File: centos8-relay-bin.000002
Relay_Log_Pos: 657
Relay_Master_Log_File: mysql-bin.000002
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: 444
Relay_Log_Space: 866
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: 8
Master_UUID: 1e248f34-0ed4-11eb-bfe2-000c298d3e41
Master_Info_File: /data/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 1e248f34-0ed4-11eb-bfe2-000c298d3e41:1
Executed_Gtid_Set: 1e248f34-0ed4-11eb-bfe2-000c298d3e41:1
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
(1)清理日志
PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
RESET MASTER TO # #mysql不支持
RESET SLAVE [ALL]
(2)复制监控
SHOW MASTER STATUS
SHOW BINARY LOGS
SHOW BINLOG EVENTS
SHOW SLAVE STATUS
SHOW PROCESSLIST
(3)从服务器是否落后于主服务
Seconds_Behind_Master: 0
(4)如何确定主从节点数据是否一致
percona-toolkit
(5)数据不一致如何修复
删除从数据库,重新复制
重新复制
1.造成主从不一致的原因
2.主从不一致修复方法
1.从库停止slave复制
mysql>stop slave;
2.在主库上dump这三张表,并记录下同步的binlog和POS点
mysqldump -uroot -pcentos -q --single-transaction --master-data=2 testdb A B C > /backup/A_B_C.sql
3.查看A_B_C.sql 文件,找出记录的binlog和POS点
head A_B_C.sql
例如:MASTERLOGFILE='mysql-bin.8.8.8.8',MASTERLOGPOS=666666;
#以下指令是为了保障其他表的数据不丢失,一直同步直到那个点结束,A,B,C表的数据在之前的备份已经生成了一份快照,只需要导入进去,然后开启同步即可
4.把A_B_C.sql拷贝到Slave机器上,并指向新位置
mysql>start slave until MASTERLOGFILE='mysql-bin.888888',MASTERLOGPOS=666666;
5、在Slave机器上导入A_B_C.sql
mysql -uroot -pmagedu testdb
mysql>set sql_log_bin=0;
mysql>source /backup/A_B_C.sql
mysql>set sql_log_bin=1;
6、导入完毕后,从库开启同步即可。
mysql>start slave;
3.如何避免主从不一致
数据库主要分为两大类:关系型数据库与 NoSQL 数据库
关系型数据库,是建立在关系模型基础上的数据库,其借助于集合代数等数学概念和方法来处理数据库中的数据。主流的MySQL、Oracle、MS SQL Server和DB2都属于这类传统数据库
NoSQL 数据库,全称为Not Only SQL,意思就是适用关系型数据库的时候就使用关系型数据库,不适用的时候也没有必要使用关系型数据库不可,可以考虑使用更加合适的数据存储。主要分为临时性键值存储(memcached、Redis)、永久性键值存储(ROMA、Redis)、面向文档的数据库(MongoDB、CouchDB)、面向列的数据库(Cassandra、Hbase),每种NoSQL都有其特有的使用场景及优点
Oracle,mysql等传统的关系型数据库非常成熟并且已大规模商用,为什么还要用NoSQL数据库呢?主要是由于随着互联网发展,数据量越来越大,对性能要求越来越高,传统数据库存在着先天性的缺陷,即单机(单库)性能瓶颈,并且扩展困难。这样既有单机单库瓶颈,却又扩展困难,自然无法满足日益增长的海量数据存储及其性能要求,所以才会出现了各种不同的NoSQL产品,NoSQL根本性的优势在于在云计算时代,简单、易于大规模分布式扩展,并且读写性能非常高
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果
数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式
一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分;另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。
垂直切分的最大特点就是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非常低,相互影响很小,业务逻辑非常清晰的系统。在这种系统中,可以很容易做到将不同业务模块所使用的表分拆到不同的数据库中。根据不同的表来进行拆分,对应用程序的影响也更小,拆分规则也会比较简单清晰。
水平切分于垂直切分相比,相对来说稍微复杂一些。因为要将同一个表中的不同数据拆分到不同的数据库中,对于应用程序来说,拆分规则本身就较根据表名来拆分更为复杂,后期的数据维护也会更为复杂一些。
一个数据库有很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如下图:
系统被切分成了,用户,订单交易,支付几个模块。一个架构设计较好的应用系统,其总体功能肯定是由很多功能模块所组成的,而每一个功能模块所需要的数据对应到数据库中就是一个或者多个表。而在架构设计中,各个功能模块相互之间的交互点越统一越少,系统的耦合度就越低,系统各个模块的维护性以及扩展性也就越好。这样的系统,实现数据的垂直切分也就越容易。
但是往往系统之中有些表难以做到完全独立,存在着跨库join的情况,对于这类表,就需要去做平衡,是数据库让步业务,共用一个数据源,还是分成多个库,业务之间通过接口来做调用。在系统初期,数据量比较少,或者资源有限你的情况下,会选择共用数据源,但是当数据发展到了一定的规模,负载很大的情况,就需要必须去做分割。
一般来讲业务存在着复杂join的场景是难以切分的,往往业务独立的易于切分。如何切分,切分到何种程度是考验技术架构的一个难题。
垂直切分的优缺点:
优点:
由于垂直切分是根据业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决。
对应shard中查询相关数据
相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分 到一个数据库,而另外的某些行又切分到其他的数据库中,如图:
拆分数据就需要定义分片规则。关系型数据库是行列的二维模型,拆分的第一原则是找到拆分维度。比如: 从会员的角度来分析,商户订单交易类系统中查询会员某天某月某个订单,那么就需要按照会员结合日期来拆分, 不同的数据按照会员 ID 做分组,这样所有的数据查询 join 都会在单库内解决;如果从商户的角度来讲,要查询某 个商家某天所有的订单数,就需要按照商户 ID 做拆分;但是如果系统既想按会员拆分,又想按商家数据,则会有 一定的困难。如何找到合适的分片规则需要综合考虑衡量。
几种典型的分片规则包括:
如图,切分原则都是根据业务找到适合的切分规则分散到不同的库,下面用用户 ID 求模举例:
既然数据做了拆分有优点也就有缺点。
优点:
缺点:
前面讲了垂直切分跟水平切分的不同跟优缺点,会发现每种切分方式都有缺点,但共同特点缺点有:
针对数据源管理,目前主要有两种思路:
A. 客户端模式,在每个应用程序模块中配置管理自己需要的一个(或者多个)数据源,直接访问各个数据库, 在模块内完成数据的整合
B. 通过中间代理层来统一管理所有的数据源,后端数据库集群对前端应用程序透明; 可能 90%以上的人在面对上面这两种解决思路的时候都会倾向于选择第二种,尤其是系统不断变得庞大复杂 的时候。确实,这是一个非常正确的选择,虽然短期内需要付出的成本可能会相对更大一些,但是对整个系统的 扩展性来说,是非常有帮助的。
MySQL中间件服务器可以通过将数据切分解决传统数据库的缺陷,又有了 NoSQL 易于扩展的优点。通过中间代理层规避了多数 据源的处理问题,对应用完全透明,同时对数据切分后存在的问题,也做了解决方案。
由于数据切分后数据 Join 的难度在此也分享一下数据切分的经验:
第一原则:能不切分尽量不要切分
第二原则:如果要切分一定要选择合适的切分规则,提前规划好。
第三原则:数据切分尽量通过数据冗余或表分组(Table Group)来降低跨库 Join 的可能第四原则:由于数据库中间件对数据 Join 实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量 少使用多表 Join。
mysql-proxy:Oracle,https://downloads.mysql.com/archives/proxy/
Atlas:Qihoo,https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md
dbproxy:美团,https://github.com/Meituan-Dianping/DBProxy
Cetus:网易乐得,https://github.com/Lede-Inc/cetus
Amoeba:https://sourceforge.net/projects/amoeba/
Cobar:阿里巴巴,Amoeba的升级版, https://github.com/alibaba/cobar
Mycat:基于Cobar http://www.mycat.io/ (原网站)
http://www.mycat.org.cn/
https://github.com/MyCATApache/Mycat-Server
ProxySQL:https://proxysql.com/
在整个IT系统架构中,数据库是非常重要,通常又是访问压力较大的一个服务,除了在程序开发的本身做优化,如:SQL语句优化、代码优化,数据库的处理本身优化也是非常重要的。主从、热备、分表分库等都是系统发展迟早会遇到的技术问题问题。Mycat是一个广受好评的数据库中间件,已经在很多产品上进行使用了。
Mycat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理(类似于Mysql Proxy),用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。
Mycat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度
Mycat 可以简单概括为:
Mycat 官网: http://www.mycat.org.cn/
Mycat 关键特性
为什么要用MyCat
这里要先搞清楚Mycat和MySQL的区别(Mycat的核心作用)。我们可以把上层看作是对下层的抽象,例如操作系统是对各类计算机硬件的抽象。那么我们什么时候需要抽象?假如只有一种硬件的时候,我们需要开发一个操作系统吗?再比如一个项目只需要一个人完成的时候不需要leader,但是当需要几十人完成时,就应该有一个管理者,发挥沟通协调等作用,而这个管理者对于他的上层来说就是对项目组的抽象
同样的,当我们的应用只需要一台数据库服务器的时候我们并不需要Mycat,而如果你需要分库甚至分表,这时候应用要面对很多个数据库的时候,这个时候就需要对数据库层做一个抽象,来管理这些数据库,而最上面的应用只需要面对一个数据库层的抽象或者说数据库中间件就好了,这就是Mycat的核心作用。所以可以这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象
Mycat工作原理
Mycat的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户
Mycat应用场景
Mycat适用的场景很丰富,以下是几个典型的应用场景
Mycat不适合的应用场景
MyCat的高可用性:
需要注意: 在生产环境中, Mycat节点最好使用双节点, 即双机热备环境, 防止Mycat这一层出现单点故障.
可以使用的高可用集群方式有:
下载安装JDK
yum -y install java
#确认安装成功
java -version
openjdk version "1.8.0_201"
OpenJDK Runtime Environment (build 1.8.0_201-b09)
OpenJDK 64-Bit Server VM (build 25.201-b09, mixed mode)
下载安装mycat
wget http://dl.mycat.org.cn/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
mkdir /apps
tar xvf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz -C /apps
ls /apps/mycat/
bin catlet conf lib logs version.txt
mycat安装目录结构:
logs目录:
Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:
启动和连接
#配置环境变量
vim /etc/profile.d/mycat.sh
PATH=/apps/mycat/bin:$PATH
source /etc/profile.d/mycat.sh
#启动
mycat start
#查看日志,确定成功
cat /apps/mycat/logs/wrapper.log
...省略...
INFO | jvm 1 | 2019/11/01 21:41:02 | MyCAT Server startup successfully. see logs in logs/mycat.log
#连接mycat
mysql -uroot -pcentos -h127.0.0.1 -P8066
server.xml
存放Mycat软件本身相关的配置文件,比如:连接Mycat的用户,密码,数据库名称等
server.xml文件中配置的参数解释说明:
参数 说明
user 用户配置节点
name 客户端登录MyCAT的用户名,也就是客户端用来连接Mycat的用户名。
password 客户端登录MyCAT的密码
schemas 数据库名,这里会和schema.xml中的配置关联,多个用逗号分开,例如:db1,db2
privileges 配置用户针对表的增删改查的权限
readOnly mycat逻辑库所具有的权限。true为只读,false为读写都有,默认为false
注意:
schema.xml
是最主要的配置项,此文件关联mysql读写分离策略,读写分离、分库分表策略、分片节点都是在此文件中配置的.MyCat作为中间件,它只是一个代理,本身并不进行数据存储,需要连接后端的MySQL物理服务器,此文件就是用来连接MySQL服务器的
schema.xml文件中配置的参数解释说明:
参数 说明
schema 数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应
dataNode 分片信息,也就是分库相关配置
dataHost 物理数据库,真正存储数据的数据库
配置说明
name属性唯一标识dataHost标签,供上层的标签使用。
maxCon属性指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、readHost标签都会使用这个属性的值来实例化出连接池的最大连接数
minCon属性指定每个读写实例连接池的最小连接,初始化连接池的大小
每个节点的属性逐一说明
schema:
属性 说明
name 逻辑数据库名,与server.xml中的schema对应
checkSQLschema 数据库前缀相关设置,这里为false
sqlMaxLimit select 时默认的limit,避免查询全表
table
属性 说明
name 表名,物理数据库中表名
dataNode 表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name
primaryKey 主键字段名,自动生成主键时需要设置
autoIncrement 是否自增
rule 分片规则名,具体规则下文rule详细介绍
dataNode
属性 说明
name 节点名,与table中dataNode对应
datahost 物理数据库名,与datahost中name对应
database 物理数据库中数据库名
dataHost
属性 说明
name 物理数据库名,与dataNode中dataHost对应
balance 均衡负载的方式
writeType 写入方式
dbType 数据库类型
heartbeat 心跳检测语句,注意语句结尾的分号要加
schema.xml文件中有三点需要注意:balance=“1”,writeType=“0” ,switchType=“1”
schema.xml中的balance的取值决定了负载均衡对非事务内的读操作的处理。balance 属性负载均衡类型,目前的取值有 4 种:
balance=“0”:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上,即读请求仅发送到writeHost上
balance=“1”:一般用此模式,读请求随机分发到当前writeHost对应的readHost和standby的writeHost上。即全部的readHost与stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 , M2->S2,并且 M1 与 M2 互为主备),正常情况下, M2,S1, S2 都参与 select语句的负载均衡
balance=“2”:读请求随机分发到当前dataHost内所有的writeHost和readHost上。即所有读操作都随机的在writeHost、 readhost 上分发
balance=“3”:读请求随机分发到当前writeHost对应的readHost上。即所有读请求随机的分发到wiriterHost 对应的 readhost 执行, writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有
writeHost和readHost 标签
这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池。
唯一不同的是:writeHost指定写实例、readHost指定读实例,组合这些读写实例来满足系统的要求。
在一个dataHost内可以定义多个writeHost和readHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去
注意:
Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的
主从复制将数据复制到readhost
注意:
Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的主从复制将数据复制到readhost
cat /etc/centos
CentOS Linux release 8.0.1905 (Core)
服务器共四台
client 10.0.0.7
mycat-server 10.0.0.8 #内存建议2G以上
mysql-master 10.0.0.18
mysql-slave 10.0.0.28
关闭SELinux和防火墙
systemctl stop firewalld
setenforce 0
时间同步
1.创建MySQL主从数据库
#在master和slave上
[root@mysql-master ~]#yum -y install mariadb-server
[root@mysql-slave ~]#yum -y install mariadb-server
1)修改master和slave的配置文件
#master上的my.cnf
[root@mysql-master ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
log-bin
[root@mysql-master ~]#systemctl enable --now mariadb
#在slave上的my.cnf
[root@mysql-slave ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=28
read-only
[root@mysql-slave ~]#systemctl enable --now mariadb
2)Master上创建复制用户
[root@mysql-master ~]#mysql
MariaDB [(none)]> grant replication slave on *.* to kobe@'10.0.0.%' identified by 'centos';
MariaDB [(none)]> flush privileges;
MariaDB [(none)]> show master status;
+--------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+--------------------+----------+--------------+------------------+
| mariadb-bin.000003 | 658 | | |
+--------------------+----------+--------------+------------------+
1 row in set (0.000 sec)
3)slave上执行
[root@mysql-slave ~]#mysql
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.18',
-> MASTER_USER='kobe',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000003',
-> MASTER_LOG_POS=658;
Query OK, 0 rows affected (0.330 sec)
MariaDB [(none)]> start slave;
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.18
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000003
Read_Master_Log_Pos: 658
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 557
Relay_Master_Log_File: mariadb-bin.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: 658
Relay_Log_Space: 868
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: 18
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
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: 0
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.000 sec)
2.在MySQL代理服务器10.0.0.8安装mycat并启动
[root@mycat-server ~]#yum -y install java mariadb
#确认安装成功
[root@mycat-server ~]#java -version
openjdk version "1.8.0_201"
OpenJDK Runtime Environment (build 1.8.0_201-b09)
OpenJDK 64-Bit Server VM (build 25.201-b09, mixed mode)
#下载并安装
[root@mycat-server ~]#wget http://dl.mycat.org.cn/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
[root@mycat-server ~]#mkdir /apps
[root@mycat-server ~]#tar xf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz -C /apps/
#配置环境变量
[root@mycat-server ~]#echo "PATH=/apps/mycat/bin:$PATH" > /etc/profile.d/mycat.sh
[root@mycat-server ~]#source /etc/profile.d/mycat.sh
#查看端口
[root@mycat-server ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 100 127.0.0.1:25 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 100 [::1]:25 [::]:*
#启动mycat
[root@mycat-server ~]#file /apps/mycat/bin/mycat
/apps/mycat/bin/mycat: POSIX shell script, ASCII text executable
[root@mycat-server ~]#mycat
Usage: /apps/mycat/bin/mycat { console | start | stop | restart | status | dump }
#注意: 此步启动较慢,需要等一会,另外如果内存太小,会导致无法启动
[root@mycat-server ~]#mycat start
Starting Mycat-server...
#可以看到打开多个端口,其中8066端口用于连接MyCAT
[root@mycat-server ~]#ss -ntlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=936,fd=5))
LISTEN 0 100 127.0.0.1:25 0.0.0.0:* users:(("master",pid=1212,fd=16))
LISTEN 0 1 127.0.0.1:32000 0.0.0.0:* users:(("java",pid=4735,fd=4))
LISTEN 0 50 *:36853 *:* users:(("java",pid=4735,fd=64))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=936,fd=7))
LISTEN 0 100 [::1]:25 [::]:* users:(("master",pid=1212,fd=17))
LISTEN 0 50 *:42045 *:* users:(("java",pid=4735,fd=66))
LISTEN 0 50 *:1984 *:* users:(("java",pid=4735,fd=65))
LISTEN 0 100 *:8066 *:* users:(("java",pid=4735,fd=89))
LISTEN 0 100 *:9066 *:* users:(("java",pid=4735,fd=85))
#查看日志,确定成功,可能需要等一会儿才能看到成功的提示
[root@mycat-server ~]#tail /apps/mycat/logs/wrapper.log
STATUS | wrapper | 2020/10/15 21:45:48 | --> Wrapper Started as Daemon
STATUS | wrapper | 2020/10/15 21:45:48 | Launching a JVM...
INFO | jvm 1 | 2020/10/15 21:45:50 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO | jvm 1 | 2020/10/15 21:45:50 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
INFO | jvm 1 | 2020/10/15 21:45:50 |
INFO | jvm 1 | 2020/10/15 21:45:56 | MyCAT Server startup successfully. see logs in logs/mycat.log
#用默认密码123456来连接mycat
[root@client ~]# mysql -uroot -p123456 -h 10.0.0.8 -P8066
MySQL [(none)]> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB |
+----------+
1 row in set (0.01 sec)
MySQL [(none)]> use TESTDB
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
MySQL [TESTDB]> show tables;
+------------------+
| Tables in TESTDB |
+------------------+
| address |
| travelrecord |
+------------------+
2 rows in set (0.00 sec)
MySQL [TESTDB]> select * from travelrecord;
ERROR 1105 (HY000): backend connect: java.lang.IllegalArgumentException: Invalid DataSource:0
4.在mycat 服务器上修改server.xml文件配置Mycat的连接信息
#连接Mycat的用户名
centos #连接Mycat的密码
TESTDB #数据库名要和schema.xml相对应
TESTDB
这里使用的是root,密码为centos,逻辑数据库为TESTDB,这些信息都可以自己随意定义,读写权限都有,没有针对表做任何特殊的权限.重点关注上面这段配置,其它默认即可
5.修改schema.xml实现读写分离策略
#配置范例
[root@mycat-server ~]#vim /apps/mycat/conf/schema.xml
select user()
#重新启动mycat
[root@mycat-server ~]#mycat restart
上面配置中,balance改为1,表示读写分离。以上配置达到的效果就是10.0.0.18为主库,10.0.0.28为从库
注意:要保证能使用root/centos权限成功登录10.0.0.18和10.0.0.28机器上面的mysql数据库。同时,也一定要授权mycat机器能使用root/centos权限成功登录这两台机器的mysql数据库!!这很重要,否则会导致登录mycat后,对库和表操作失败!
范例:schema.xml
6.在后端主服务器创建用户并对mycat授权
[root@mysql-master ~]#mysql
MariaDB [(none)]> create database mycat;
MariaDB [(none)]> grant all on *.* to root@'10.0.0.%' identified by 'centos';
MariaDB [(none)]> flush privileges;
7.在Mycat服务器上连接并测试
[root@mycat-server ~]#mysql -uroot -pcentos -h127.0.0.1 -P8066 -DTESTDB
#只能看一个虚拟数据库TESTDB
MySQL [TESTDB]> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB |
+----------+
1 row in set (0.001 sec)
MySQL [TESTDB]> use TESTDB
MySQL [TESTDB]> create table test(id int);
MySQL [TESTDB]> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 28 |
+-------------+
1 row in set (0.003 sec)
MySQL [TESTDB]> select @@hostname;
+----------------------+
| @@hostname |
+----------------------+
| mysql-slave.kobe.com |
+----------------------+
1 row in set (0.004 sec)
8.通过通用日志确认实现读写分离
在mysql中查看通用日志
show variables like 'general_log'; #查看日志是否开启
set global general_log=on; #开启日志功能
show variables like 'general_log_file'; #查看日志文件保存位置
set global general_log_file='tmp/general.log'; #设置日志文件保存位置
在主和从服务器分别启用通用日志,查看读写分离
#修改master配置文件
[root@mysql-master ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
log-bin
general_log=ON
[root@mysql-master ~]#systemctl restart mariadb
[root@mysql-master ~]#tail -f /var/lib/mysql/mysql-master.log
201015 22:27:29 9 Query select user()
201015 22:27:39 9 Query select user()
12 Connect [email protected] as anonymous on mycat
13 Connect [email protected] as anonymous on mycat
14 Connect [email protected] as anonymous on mycat
201015 22:27:49 12 Query select user()
201015 22:27:59 13 Query select user()
201015 22:28:09 14 Query select user()
201015 22:28:19 9 Query select user()
201015 22:28:29 12 Query select user()
201015 22:28:39 13 Query select user()
201015 22:28:49 14 Query select user()
201015 22:28:59 9 Query select user()
201015 22:29:09 12 Query select user()
201015 22:29:19 13 Query select user()
201015 22:29:29 14 Query select user()
201015 22:29:39 9 Query select user()
201015 22:29:49 12 Query select user()
201015 22:29:59 13 Query select user()
##修改slave配置文件
[root@mysql-slave ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=28
read-only
general_log=ON
[root@mysql-slave ~]#systemctl restart mariadb
[root@mysql-slave ~]#tail -f /var/lib/mysql/mysql-slave.log
201015 22:27:49 11 Query select user()
201015 22:27:59 12 Query select user()
201015 22:28:09 13 Query select user()
201015 22:28:19 14 Query select user()
201015 22:28:29 11 Query select user()
201015 22:28:39 12 Query select user()
201015 22:28:49 13 Query select user()
201015 22:28:59 14 Query select user()
201015 22:29:09 11 Query select user()
201015 22:29:19 12 Query select user()
201015 22:29:29 13 Query select user()
201015 22:29:39 14 Query select user()
9.停止从节点,MyCAT自动调度读请求至主节点
[root@mysql-slave ~]#systemctl stop mariadb
#在client上
[root@client ~]# mysql -uroot -pcentos -h 10.0.0.8 -P8066
MySQL [(none)]> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 18 |
+-------------+
1 row in set (0.06 sec)
MySQL [(none)]> select @@hostname;
+-----------------------+
| @@hostname |
+-----------------------+
| mysql-master.kobe.com |
+-----------------------+
1 row in set (0.00 sec)
#停止主节点,启动从节点,MyCAT不会自动调度写请求至从节点
[root@mysql-master ~]#systemctl stop mariadb
[root@mysql-slave ~]#systemctl start mariadb
MySQL [TESTDB]> insert teachers values(5,'wang',30,'M');
ERROR 1184 (HY000): java.net.ConnectException: Connection refused
ProxySQL:MySQL中间件
两个版本:官方版和percona版,percona版是基于官方版基础上修改
C++语言开发,轻量级但性能优异,支持处理千亿级数据
具有中间件所需的绝大多数功能,包括:
多种方式的读/写分离
定制基于用户、基于schema、基于语句的规则对SQL语句进行路由
查询缓存结果
后端节点监控
官方站点:https://proxysql.com/
官方手册:https://github.com/sysown/proxysql/wiki
基于YUM仓库安装
cat <
ProxySQL组成
启动ProxySQL:
service proxysql start
启动后会监听两个默认端口
连接ProxySQL的管理端口
使用mysql客户端连接到ProxySQL的管理接口6032,默认管理员用户和密码都是admin
mysql -uadmin -padmin -P6032 -h127.0.0.1
数据库说明:
说明:
在main和monitor数据库中的表,runtime开头的是运行时的配置,不能修改,只能修改非runtime表
修改后必须执行LOAD … TO RUNTIME才能加载到RUNTIME生效
执行save … to disk 才将配置持久化保存到磁盘,即保存在proxysql.db文件中
global_variables有许多变量可以设置,其中就包括监听的端口、管理账号等
参考: https://github.com/sysown/proxysql/wiki/Global-variables
1.环境准备:
准备三台主机,一台ProxySQL服务器:10.0.0.7,另外两台主机实现主从复制10.0.0.17,10.0.0.27
#搭建主从复制环境
1)在master上
[root@master ~]# yum -y install mariadb-server
[root@master ~]# vim /etc/my.cnf
[mysqld]
server-id=17
log-bin
[root@master ~]# systemctl enable --now mariadb
[root@master ~]# mysql
MariaDB [(none)]> grant replication slave on *.* to kobe@'10.0.0.%' identified by 'centos';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show master logs;
+--------------------+-----------+
| Log_name | File_size |
+--------------------+-----------+
| mariadb-bin.000001 | 392 |
+--------------------+-----------+
1 row in set (0.00 sec)
[root@master ~]# mysqldump -A -F --single-transaction --master-data=1 > allbackup.sql
[root@master ~]# scp allbackup.sql 10.0.0.27:
2)在slave上
[root@slave ~]# yum -y install mariadb-server
[root@slave ~]# vim /etc/my.cnf
[mysqld]
server-id=27
read-only
[root@slave ~]# systemctl enable --now mariadb
[root@slave ~]# vim allbackup.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.17',
MASTER_USER='kobe',
MASTER_PASSWORD='centos',
MASTER_PORT=3306,
MASTER_LOG_FILE='mariadb-bin.000002',
MASTER_LOG_POS=245;
[root@slave ~]# mysql < allbackup.sql
[root@slave ~]# mysql
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.17
Master_User: kobe
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000002
Read_Master_Log_Pos: 245
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 531
Relay_Master_Log_File: mariadb-bin.000002
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: 245
Relay_Log_Space: 827
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: 17
1 row in set (0.00 sec)
注意:slave节点需要设置read_only=1
2.安装ProxySQL,并向ProxySQL中添加MySQL节点,以下操作不需要use main也可成功
[root@proxysql ~]# wget https://github.com/sysown/proxysql/releases/download/v2.0.14/proxysql-2.0.14-1-centos7.x86_64.rpm
[root@proxysql ~]# yum -y install proxysql-2.0.14-1-centos7.x86_64.rpm
[root@proxysql ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 *:6032 *:*
LISTEN 0 128 *:6033 *:*
LISTEN 0 128 *:6033 *:*
LISTEN 0 128 *:6033 *:*
LISTEN 0 128 *:6033 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 [::1]:25 [::]:*
LISTEN 0 128 [::]:22 [::]:*
[root@proxysql ~]# yum -y install mariadb
[root@proxysql ~]# mysql -uadmin -padmin -P6032 -h127.0.0.1
MySQL [(none)]> show tables;
MySQL [(none)]> select * from sqlite_master where name='mysql_server'\G
Empty set (0.00 sec)
MySQL [(none)]> select * from mysql_servers;
Empty set (0.01 sec)
MySQL [(none)]> insert into mysql_servers(hostgroup_id,hostname,port) values(10,'10.0.0.17',3306);
Query OK, 1 row affected (0.00 sec)
MySQL [(none)]> insert into mysql_servers(hostgroup_id,hostname,port) values(20,'10.0.0.27',3306);
Query OK, 1 row affected (0.00 sec)
MySQL [(none)]> load mysql servers to runtime;
Query OK, 0 rows affected (0.02 sec)
MySQL [(none)]> save mysql servers to disk;
Query OK, 0 rows affected (0.02 sec)
3.添加监控后端节点的用户,连接每个节点的read_only值来自动调整主从节点是属于读组还是写组
#在master上执行
MariaDB [(none)]> grant replication client on *.* to monitor@'10.0.0.%' identified by 'centos';
Query OK, 0 rows affected (0.00 sec)
#在ProxySQL上配置监控
MySQL [(none)]> set mysql-monitor_username='monitor';
Query OK, 1 row affected (0.00 sec)
MySQL [(none)]> set mysql-monitor_password='centos';
Query OK, 1 row affected (0.00 sec)
#加载到RUNTIME,并保存到disk
MySQL [(none)]> load mysql variables to runtime;
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]> save mysql variables to disk;
Query OK, 136 rows affected (0.00 sec)
4.查看监控
监控模块的指标保存在monitor库的log表中
#查看监控连接是否正常的(对connect指标的监控),如果connect_error的结果为NULL则表示正常
MySQL [(none)]> select * from mysql_server_connect_log;
+-----------+------+------------------+-------------------------+-------------------------------------------------------------------+
| hostname | port | time_start_us | connect_success_time_us | connect_error |
+-----------+------+------------------+-------------------------+-------------------------------------------------------------------+
| 10.0.0.27 | 3306 | 1602853404999178 | 1721 | NULL |
| 10.0.0.17 | 3306 | 1602853405837532 | 2223 | NULL |
+-----------+------+------------------+-------------------------+-------------------------------------------------------------------+
2 rows in set (0.00 sec)
#查看监控心跳信息(对ping指标的监控)
MySQL [(none)]> select * from mysql_server_ping_log;
5.设置分组信息
需要修改的是main库中的mysql_replication_hostgroups表,该表有3个字段:writer_hostgroup,reader_hostgroup,commit,指定写组的id为10,读组的id为20
#Monitor模块监控后端的read_only值,按照read_only的值将节点自动移动到读/写组
MySQL [mysql]> select hostgroup_id,hostname,port,status,weight from mysql_servers;
+--------------+-----------+------+--------+--------+
| hostgroup_id | hostname | port | status | weight |
+--------------+-----------+------+--------+--------+
| 10 | 10.0.0.17 | 3306 | ONLINE | 1 |
| 20 | 10.0.0.27 | 3306 | ONLINE | 1 |
+--------------+-----------+------+--------+--------+
2 rows in set (0.00 sec)
6.配置访问数据库的SQL 用户
#在master节点上创建访问用户
MariaDB [(none)]> grant all on *.* to sqluser@'10.0.0.%' identified by 'centos';
Query OK, 0 rows affected (0.00 sec)
#在ProxySQL配置,将用户sqluser添加到mysql_user表中,default_hostgroup默认组设置为写组10,当读写分离的路由规则不符合时,会访问默认组的数据库
MySQL [mysql]> insert into mysql_users(username,password,default_hostgroup) values('sqluser','centos',10);
Query OK, 1 row affected (0.00 sec)
MySQL [mysql]> load mysql users to runtime;
Query OK, 0 rows affected (0.00 sec)
MySQL [mysql]> save mysql users to disk;
Query OK, 0 rows affected (0.01 sec)
#使用sqluser用户测试是否能路由到默认的10写组实现读、写数据
[root@proxysql ~]# mysql -usqluser -pcentos -P6033 -h127.0.0.1 -e 'select @@server_id';
+-------------+
| @@server_id |
+-------------+
| 17 |
+-------------+
[root@proxysql ~]# mysql -usqluser -pcentos -P6033 -h127.0.0.1 -e 'create database testdb'
[root@proxysql ~]# mysql testdb -usqluser -pcentos -P6033 -h127.0.0.1 -e 'create table t1(id int)'
7.在proxysql上配置路由规则,实现读写分离
与规则有关的表:mysql_query_rules和mysql_query_rules_fast_routing,后者是前者的扩展表,1.4.7之后支持
插入路由规则:将select语句分离到20的读组,select语句中有一个特殊语句SELECT … FOR UPDATE它会申请写锁,应路由到10的写组
MySQL [(none)]> insert into mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) values(1,1,'^SELECT.*FOR UPDATE$',10,1),(2,1,'^SELECT',20,1);
Query OK, 2 rows affected (0.00 sec)
MySQL [(none)]> load mysql query rules to runtime;
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]> save mysql query rules to disk;
Query OK, 0 rows affected (0.02 sec)
#注意:因ProxySQL根据规则rule_id顺序进行规则匹配,select ... for update规则的rule_id必须要小于普通的select规则的rule_id
8.测试ProxySQL
#读操作是否路由给20的读组
[root@proxysql ~]# mysql -usqluser -pcentos -P6033 -h127.0.0.1 -e 'select @@server_id'
[root@proxysql ~]# mysql -usqluser -pcentos -P6033 -h127.0.0.1 -e 'start transaction;select @@server_id;commit;select @@server_id'
[root@proxysql ~]# mysql testdb -usqluser -pcentos -P6033 -h127.0.0.1 -e 'insert t1 values(1)'
[root@proxysql ~]# mysql -usqluser -pcentos -P6033 -h127.0.0.1 -e 'select id from testdb.t'
#路由的信息:查询stats库中的stats_mysql_query_digest表
MySQL [(none)]> SELECT hostgroup hg,sum_time, count_star, digest_text FROM stats_mysql_query_digest ORDER BY sum_time DESC;
+----+----------+------------+----------------------------------+
| hg | sum_time | count_star | digest_text |
+----+----------+------------+----------------------------------+
| 20 | 50003586 | 5 | select @@server_id |
| 10 | 6020 | 1 | create table t1(id int) |
| 10 | 5259 | 2 | select @@server_id |
| 10 | 2569 | 1 | create database testdb |
| 10 | 2157 | 1 | start transaction |
| 10 | 1763 | 1 | insert t1 values(?) |
| 10 | 1506 | 1 | insert testdb.t1 values(?) |
| 10 | 1498 | 1 | insert t1 values(?) |
| 10 | 772 | 1 | create table t1(id int) |
| 10 | 409 | 1 | commit |
| 10 | 0 | 10 | select @@version_comment limit ? |
| 10 | 0 | 2 | select @@version_comment limit ? |
+----+----------+------------+----------------------------------+
12 rows in set (0.00 sec)
MySQL官方和社区里推出了很多高可用的解决方案,大体如下,仅供参考(数据引用自Percona)
这3个节点互相通信,每当有事件发生,都会向其他节点传播该事件,然后协商,如果大多数节点都同意这次的事件,那么该事件将通过,否则该事件将失败或回滚。这些节点可以是单主模型的(single-primary),也可以是多主模型的(multi-primary)。单主模型只有一个主节点可以接受写操作,主节点故障时可以自动选举主节点。多主模型下,所有节点都可以接受写操作,所以没有
master-slave的概念。
MHA集群架构
MHA工作原理
1.从宕机崩溃的master保存二进制日志事件(binlog events)
2.识别含有最新更新的slave
3.应用差异的中继日志(relay log)到其他的slave
4.应用从master保存的二进制日志事件(binlog events)
5.提升一个slave为新的master
6.使其它的slave连接新的master进行复制
注意:
为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL的半同步复制
MHA软件
MHA软件由两部分组成,Manager工具包和Node工具包
Manager工具包主要包括以下几个工具:
masterha_check_ssh 检查MHA的SSH配置状况
masterha_check_repl 检查MySQL复制状况
masterha_manger 启动MHA
masterha_check_status 检查当前MHA运行状态
masterha_master_monitor 检测master是否宕机
masterha_master_switch 故障转移(自动或手动)
masterha_conf_host 添加或删除配置的server信息
masterha_stop --conf=app1.cnf 停止MHA
masterha_secondary_check 两个或多个网络线路检查MySQL主服务器的可用
**Node 工具包:**这些工具通常由MHA Manager的脚本触发,无需人为操作,主要包括以下几个工具:
save_binary_logs #保存和复制master的二进制日志
apply_diff_relay_logs #识别差异的中继日志事件并将其差异的事件应用于其他的slave
filter_mysqlbinlog #去除不必要的ROLLBACK事件(MHA已不再使用此工具)
purge_relay_logs #清除中继日志(不会阻塞SQL线程)
MHA配置文件:
global配置,为各application提供默认配置,默认文件路径/etc/masterha_default.cnf
application配置:为每个主从复制集群
环境:四台主机
10.0.0.7 CentOS7 MHA管理端
10.0.0.8 CentOS8 Master
10.0.0.18 CentOS8 Slave1
10.0.0.28 CentOS8 Slave2
[root@mha ~]# ssh-keygen
[root@mha ~]# ssh-copy-id 127.0.0.1
[root@mha ~]# rsync -a .ssh 10.0.0.8:/root/
[root@mha ~]# rsync -a .ssh 10.0.0.18:/root/
[root@mha ~]# rsync -a .ssh 10.0.0.28:/root/
说明:mha4mysql-manager-0.56-0.el6.noarch.rpm 不支持CentOS8,只支持CentOS7以下版本
说明:mha4mysql-manager-0.58-el7.centos.noarch.rpm,支持MySQL5.7,但和CentOS8版本上的Mariadb-10.3.17不兼容
[root@mha ~]# yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[root@mha ~]# yum -y install mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
[root@mha ~]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm 10.0.0.8:
[root@mha ~]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm 10.0.0.18:
[root@mha ~]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm 10.0.0.28:
此包支持CentOS 8,7,6
#在master上
[root@Master ~]#yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
#在slave1上
[root@Slave1 ~]#yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
#在slave2上
[root@Slave2 ~]#yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[root@mha ~]# mkdir /etc/mastermha
[root@mha ~]# vim /etc/mastermha/app1.cnf
[server default]
user=kobe #用于远程连接MySQL所有节点的用户,需要有管理员的权限
password=centos
manager_workdir=/data/mastermha/app1 #目录会自动生成,无需手动创建
manager_log=/data/mastermha/app1/manager.log
remote_workdir=/data/mastermha/app1
ssh_user=root #用于实现远程ssh基于KEY的连接,访问二进制日志
repl_user=bryant #主从复制的用户信息
repl_password=centos
ping_interval=1 #健康性检查的时间间隔
master_ip_failover_script=/usr/local/bin/master_ip_failover #切换VIP的perl脚本
report_script=/usr/local/bin/sendmail.sh #执行报警脚本
check_repl_delay=0 #默认如果从slave中从库落后主库relaylog超过100M,主库不会选择这个从库为新的master,因为这个从库进行恢复需要很长的时间,通过这个参数,mha触发主从切换时会忽略复制的延时,对于设置candidate_master=1的从库非常有用,这样确保这个从库一定能成为新的master
master_binlog_dir=/data/mysqllogbin #指定二进制日志存放的目录,mha4mysql-manager-0.58必须指定,之前版本不需要指定
[server1]
hostname=10.0.0.8
candidate_master=1
[server2]
hostname=10.0.0.18
candidate_master=1 #设置为优先候选master,即使不是集群中事件最新的slave,也会优先当选master
[server3]
hostname=10.0.0.28
说明:主库宕机谁来接管新的master
1.所有从节点日志都是一致的,默认会以配置文件的顺序去选择一个新主
2.从节点日志不一致,自动选择最接近于主库的从库充当新主
3.如果对于某节点设定了权重(candidate_master=1),权重节点会优先选择。但是此节点日志量落后主库超过100M日志的话,也不会被选择。可以配合check_repl_delay=0,关闭日志量的检查,强制选择候选节点
[root@mha ~]# yum -y install mailx
[root@mha ~]# vim /etc/mail.rc
set [email protected]
set smtp=smtp.qq.com
set [email protected]
set smtp-auth-password=rikznelgouxkdfbg
set smtp-auth=login
[root@mha ~]# systemctl restart postfix.service
[root@mha ~]# vim /usr/local/bin/sendmail.sh
echo "MySQL is down" | mail -s "MHA warining" [email protected]
[root@mha ~]# chmod +x /usr/local/bin/sendmail.sh
[root@mha ~]# vim /usr/local/bin/master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);
my $vip = '10.0.0.100/24';#设置Virtual IP
my $gateway = '10.0.0.2';#网关Gateway IP
my $interface = 'eth0'; #指定VIP所在网卡
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig $interface:$key $vip;/sbin/arping -I
$interface -c 3 -s $vip $gateway >/dev/null 2>&1";
my $ssh_stop_vip = "/sbin/ifconfig $interface:$key down";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);
exit &main();
sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --
orig_master_host=host --orig_master_ip=ip --orig_master_port=port --
new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
[root@mha ~]# chmod +x /usr/local/bin/master_ip_failover
#在master 上
通用二进制安装MySQL5.7
[root@Master ~]#ll 1.sh mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
-rw-r--r-- 1 root root 1931 Oct 17 11:14 1.sh
-rw-r--r-- 1 root root 660017902 Sep 21 14:22 mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
[root@Master ~]#cat 1.sh
#!/bin/bash
# mysql-5.7.30 Generic URL:https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
# mysql-8.0.20 Generic URL:https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz
URL="https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz"
PACK=mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
DIR=mysql-5.7.30-linux-glibc2.12-x86_64
DIR1=/data/mysqllogbin
yum -y install ncurses-compat-libs-6.1-7.20180224.el8.x86_64 &> /dev/null
groupadd -r mysql
useradd -r -g mysql -s /sbin/nologin mysql
#wegt $URL
tar xf $PACK -C /usr/local
cd /usr/local
ln -s $DIR mysql
cd mysql
chown -R root.root ./*
echo "PATH=/usr/local/mysql/bin:$PATH" > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
ln -s /usr/local/mysql/bin/* /usr/bin
PASS1="centos"
cat > /etc/my.cnf <\\_
EOF
mysqld --initialize --user=mysql --datadir=/data/mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
service mysqld start
PASS2=`awk '/temporary password/{print $NF}' /data/mysql/mysql.log`
PASS3="centos"
mysqladmin -uroot -p"${PASS2}" password ${PASS3}
SID=`hostname -I | awk -F. '{print $4}'`
sed -ri "s#^(\[mysqld\])#\1\nserver-id=${SID}\nlog_bin=${DIR1}/mysql-bin#" /etc/my.cnf
[ -d $DIR1 ] || mkdir -p $DIR1
chown -R mysql.mysql $DIR1
service mysqld restart
[root@Master ~]#bash 1.sh
Starting MySQL...... SUCCESS!
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@Master ~]#vim /etc/my.cnf
[mysqld]
server-id=8
log_bin=/data/mysqllogbin/mysql-bin
general_log
skip_name_resolve=1
[root@Master ~]#service mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@Master ~]#mysql
(root@localhost) [(none)]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 177 |
| mysql-bin.000002 | 154 |
+------------------+-----------+
2 rows in set (0.00 sec)
(root@localhost) [(none)]> grant replication slave on *.* to bryant@'10.0.0.%' identified by 'centos';
Query OK, 0 rows affected, 1 warning (0.01 sec)
(root@localhost) [(none)]> grant all on *.* to kobe@'10.0.0.%' identified by 'centos';
Query OK, 0 rows affected, 1 warning (0.00 sec)
#配置VIP
[root@Master ~]#ip addr add 10.0.0.100/24 dev eth0 label eth0:1
#拷贝文件
[root@Master ~]#scp 1.sh mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz 10.0.0.18:
[root@Master ~]#scp 1.sh mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz 10.0.0.28:
#在salve1上
通用二进制安装MySQL5.7
[root@Slave1 ~]#bash 1.sh
Starting MySQL.. SUCCESS!
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
Shutting down MySQL. SUCCESS!
Starting MySQL. SUCCESS!
[root@Slave1 ~]#vim /etc/my.cnf
[mysqld]
server-id=18
log_bin=/data/mysqllogbin/mysql-bin
read_only
relay_log_purge=0
skip_name_resolve=1
[root@Slave1 ~]#service mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@Slave1 ~]#mysql
(root@localhost) [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='bryant',
-> MASTER_PASSWORD='centos',
-> MASTER_LOG_FILE='mysql-bin.000002',
-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.05 sec)
(root@localhost) [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)
(root@localhost) [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: bryant
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 733
Relay_Log_File: Slave1-relay-bin.000002
Relay_Log_Pos: 899
Relay_Master_Log_File: mysql-bin.000002
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: 733
Relay_Log_Space: 1107
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: 8
Master_UUID: 2cc4667c-1070-11eb-b07d-000c298d3e41
Master_Info_File: /data/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
#在slave2上
通用二进制安装MySQL5.7
[root@Slave2 ~]#bash 1.sh
Starting MySQL. SUCCESS!
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@Slave2 ~]#vim /etc/my.cnf
[mysqld]
server-id=28
log_bin=/data/mysqllogbin/mysql-bin
read_only
relay_log_purge=0
skip_name_resolve=1
[root@Slave2 ~]#service mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@Slave2 ~]#mysql
(root@localhost) [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='bryant',
-> MASTER_PASSWORD='centos',
-> MASTER_LOG_FILE='mysql-bin.000002',
-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.06 sec)
(root@localhost) [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)
(root@localhost) [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.8
Master_User: bryant
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 733
Relay_Log_File: Slave2-relay-bin.000002
Relay_Log_Pos: 899
Relay_Master_Log_File: mysql-bin.000002
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: 733
Relay_Log_Space: 1107
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: 8
Master_UUID: 2cc4667c-1070-11eb-b07d-000c298d3e41
Master_Info_File: /data/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
#检查环境
[root@mha ~]# masterha_check_ssh --conf=/etc/mastermha/app1.cnf
Sat Oct 17 12:22:11 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sat Oct 17 12:22:11 2020 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 12:22:11 2020 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 12:22:11 2020 - [info] Starting SSH connection tests..
Sat Oct 17 12:22:17 2020 - [debug]
Sat Oct 17 12:22:11 2020 - [debug] Connecting via SSH from [email protected](10.0.0.18:22) to [email protected](10.0.0.8:22)..
Sat Oct 17 12:22:15 2020 - [debug] ok.
Sat Oct 17 12:22:15 2020 - [debug] Connecting via SSH from [email protected](10.0.0.18:22) to [email protected](10.0.0.28:22)..
Sat Oct 17 12:22:17 2020 - [debug] ok.
Sat Oct 17 12:22:17 2020 - [debug]
Sat Oct 17 12:22:12 2020 - [debug] Connecting via SSH from [email protected](10.0.0.28:22) to [email protected](10.0.0.8:22)..
Sat Oct 17 12:22:16 2020 - [debug] ok.
Sat Oct 17 12:22:16 2020 - [debug] Connecting via SSH from [email protected](10.0.0.28:22) to [email protected](10.0.0.18:22)..
Sat Oct 17 12:22:17 2020 - [debug] ok.
Sat Oct 17 12:22:17 2020 - [debug]
Sat Oct 17 12:22:11 2020 - [debug] Connecting via SSH from [email protected](10.0.0.8:22) to [email protected](10.0.0.18:22)..
Sat Oct 17 12:22:15 2020 - [debug] ok.
Sat Oct 17 12:22:15 2020 - [debug] Connecting via SSH from [email protected](10.0.0.8:22) to [email protected](10.0.0.28:22)..
Sat Oct 17 12:22:17 2020 - [debug] ok.
Sat Oct 17 12:22:17 2020 - [info] All SSH connection tests passed successfully.
[root@mha ~]# masterha_check_repl --conf=/etc/mastermha/app1.cnf
Sat Oct 17 16:16:58 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sat Oct 17 16:16:58 2020 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 16:16:58 2020 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 16:16:58 2020 - [info] MHA::MasterMonitor version 0.58.
Sat Oct 17 16:17:00 2020 - [info] GTID failover mode = 0
Sat Oct 17 16:17:00 2020 - [info] Dead Servers:
Sat Oct 17 16:17:00 2020 - [info] Alive Servers:
Sat Oct 17 16:17:00 2020 - [info] 10.0.0.8(10.0.0.8:3306)
Sat Oct 17 16:17:00 2020 - [info] 10.0.0.18(10.0.0.18:3306)
Sat Oct 17 16:17:00 2020 - [info] 10.0.0.28(10.0.0.28:3306)
Sat Oct 17 16:17:00 2020 - [info] Alive Slaves:
Sat Oct 17 16:17:00 2020 - [info] 10.0.0.18(10.0.0.18:3306) Version=5.7.30-log (oldest major version between slaves) log-bin:enabled
Sat Oct 17 16:17:00 2020 - [info] Replicating from 10.0.0.8(10.0.0.8:3306)
Sat Oct 17 16:17:00 2020 - [info] Primary candidate for the new Master (candidate_master is set)
Sat Oct 17 16:17:00 2020 - [info] 10.0.0.28(10.0.0.28:3306) Version=5.7.30-log (oldest major version between slaves) log-bin:enabled
Sat Oct 17 16:17:00 2020 - [info] Replicating from 10.0.0.8(10.0.0.8:3306)
Sat Oct 17 16:17:00 2020 - [info] Current Alive Master: 10.0.0.8(10.0.0.8:3306)
Sat Oct 17 16:17:00 2020 - [info] Checking slave configurations..
Sat Oct 17 16:17:00 2020 - [info] Checking replication filtering settings..
Sat Oct 17 16:17:00 2020 - [info] binlog_do_db= , binlog_ignore_db=
Sat Oct 17 16:17:00 2020 - [info] Replication filtering check ok.
Sat Oct 17 16:17:00 2020 - [info] GTID (with auto-pos) is not supported
Sat Oct 17 16:17:00 2020 - [info] Starting SSH connection tests..
Sat Oct 17 16:17:02 2020 - [info] All SSH connection tests passed successfully.
Sat Oct 17 16:17:02 2020 - [info] Checking MHA Node version..
Sat Oct 17 16:17:03 2020 - [info] Version check ok.
Sat Oct 17 16:17:03 2020 - [info] Checking SSH publickey authentication settings on the current master..
Sat Oct 17 16:17:03 2020 - [info] HealthCheck: SSH to 10.0.0.8 is reachable.
Sat Oct 17 16:17:03 2020 - [info] Master MHA Node version is 0.58.
Sat Oct 17 16:17:03 2020 - [info] Checking recovery script configurations on 10.0.0.8(10.0.0.8:3306)..
Sat Oct 17 16:17:03 2020 - [info] Executing command: save_binary_logs --command=test --start_pos=4 --binlog_dir=/data/mysql/ --output_file=/data/mastermha/app1//save_binary_logs_test --manager_version=0.58 --start_file=mysql-bin.000004
Sat Oct 17 16:17:03 2020 - [info] Connecting to [email protected](10.0.0.8:22)..
Creating /data/mastermha/app1 if not exists.. Creating directory /data/mastermha/app1.. done.
ok.
Checking output directory is accessible or not..
ok.
Binlog found at /data/mysql/, up to mysql-bin.000004
Sat Oct 17 16:17:04 2020 - [info] Binlog setting check done.
Sat Oct 17 16:17:04 2020 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers..
Sat Oct 17 16:17:04 2020 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='kobe' --slave_host=10.0.0.18 --slave_ip=10.0.0.18 --slave_port=3306 --workdir=/data/mastermha/app1/ --target_version=5.7.30-log --manager_version=0.58 --relay_log_info=/data/mysql/relay-log.info --relay_dir=/data/mysql/ --slave_pass=xxx
Sat Oct 17 16:17:04 2020 - [info] Connecting to [email protected](10.0.0.18:22)..
Creating directory /data/mastermha/app1/.. done.
Checking slave recovery environment settings..
Opening /data/mysql/relay-log.info ... ok.
Relay log found at /data/mysql, up to Slave1-relay-bin.000002
Temporary relay log file is /data/mysql/Slave1-relay-bin.000002
Checking if super_read_only is defined and turned on.. not present or turned off, ignoring.
Testing mysql connection and privileges..
mysql: [Warning] Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Sat Oct 17 16:17:04 2020 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='kobe' --slave_host=10.0.0.28 --slave_ip=10.0.0.28 --slave_port=3306 --workdir=/data/mastermha/app1/ --target_version=5.7.30-log --manager_version=0.58 --relay_log_info=/data/mysql/relay-log.info --relay_dir=/data/mysql/ --slave_pass=xxx
Sat Oct 17 16:17:04 2020 - [info] Connecting to [email protected](10.0.0.28:22)..
Creating directory /data/mastermha/app1/.. done.
Checking slave recovery environment settings..
Opening /data/mysql/relay-log.info ... ok.
Relay log found at /data/mysql, up to Slave2-relay-bin.000002
Temporary relay log file is /data/mysql/Slave2-relay-bin.000002
Checking if super_read_only is defined and turned on.. not present or turned off, ignoring.
Testing mysql connection and privileges..
mysql: [Warning] Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Sat Oct 17 16:17:04 2020 - [info] Slaves settings check done.
Sat Oct 17 16:17:04 2020 - [info]
10.0.0.8(10.0.0.8:3306) (current master)
+--10.0.0.18(10.0.0.18:3306)
+--10.0.0.28(10.0.0.28:3306)
Sat Oct 17 16:17:04 2020 - [info] Checking replication health on 10.0.0.18..
Sat Oct 17 16:17:04 2020 - [info] ok.
Sat Oct 17 16:17:04 2020 - [info] Checking replication health on 10.0.0.28..
Sat Oct 17 16:17:04 2020 - [info] ok.
Sat Oct 17 16:17:04 2020 - [info] Checking master_ip_failover_script status:
Sat Oct 17 16:17:04 2020 - [info] /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=10.0.0.8 --orig_master_ip=10.0.0.8 --orig_master_port=3306
IN SCRIPT TEST====/sbin/ifconfig eth0:1 down==/sbin/ifconfig eth0:1 10.0.0.100/24;/sbin/arping -I
eth0 -c 3 -s 10.0.0.100/24 10.0.0.2 >/dev/null 2>&1===
Checking the Status of the script.. OK
/sbin/arping: option requires an argument -- 'I'
Usage: arping [-fqbDUAV] [-c count] [-w timeout] [-I device] [-s source] destination
-f : quit on first reply
-q : be quiet
-b : keep broadcasting, don't go unicast
-D : duplicate address detection mode
-U : Unsolicited ARP mode, update your neighbours
-A : ARP answer mode, update your neighbours
-V : print version and exit
-c count : how many packets to send
-w timeout : how long to wait for a reply
-I device : which ethernet device to use
-s source : source ip address
destination : ask for what ip address
Sat Oct 17 16:17:05 2020 - [info] OK.
Sat Oct 17 16:17:05 2020 - [warning] shutdown_script is not defined.
Sat Oct 17 16:17:05 2020 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.
[root@mha ~]# masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
#开启MHA,默认是前台运行,让其运行在后台
[root@mha ~]# masterha_manager --conf=/etc/mastermha/app1.cnf &
#查看状态
[root@mha ~]# masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 (pid:1757) is running(0:PING_OK), master:10.0.0.8
#在master上查看到健康性检查
[root@Master ~]#tail -f /data/mysql/Master.log
2020-10-17T08:34:24.266719Z 43 Query SELECT 1 As Value
2020-10-17T08:34:25.268883Z 43 Query SELECT 1 As Value
2020-10-17T08:34:26.268594Z 43 Query SELECT 1 As Value
2020-10-17T08:34:27.270373Z 43 Query SELECT 1 As Value
2020-10-17T08:34:28.269930Z 43 Query SELECT 1 As Value
[root@mha ~]# cat /data/mastermha/app1/manager.log
...省略...
Sat Oct 17 16:33:16 2020 - [info] OK.
Sat Oct 17 16:33:16 2020 - [warning] shutdown_script is not defined.
Sat Oct 17 16:33:16 2020 - [info] Set master ping interval 1 seconds.
Sat Oct 17 16:33:16 2020 - [warning] secondary_check_script is not defined. It is highly recommended setting it to check master reachability from two or more routes.
Sat Oct 17 16:33:16 2020 - [info] Starting ping health check on 10.0.0.8(10.0.0.8:3306)..
Sat Oct 17 16:33:16 2020 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
#当master down机后,mha自动退出
[root@Master ~]#service mysqld stop
Shutting down MySQL............ SUCCESS!
[root@mha ~]# masterha_manager --conf=/etc/mastermha/app1.cnf
Sat Oct 17 16:45:15 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sat Oct 17 16:45:15 2020 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 16:45:15 2020 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Creating /data/mastermha/app1 if not exists.. ok.
Checking output directory is accessible or not..
ok.
Binlog found at /data/mysql/, up to mysql-bin.000004
Creating /data/mastermha/app1 if not exists.. ok.
Checking output directory is accessible or not..
ok.
Binlog found at /data/mysql/, up to mysql-bin.000004
Sat Oct 17 16:45:24 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sat Oct 17 16:45:24 2020 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 16:45:24 2020 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 16:45:26 2020 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sat Oct 17 16:45:26 2020 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sat Oct 17 16:45:26 2020 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
[root@mha ~]# cat /data/mastermha/app1/manager.log
...省略...
Started automated(non-interactive) failover.
Invalidated master IP address on 10.0.0.8(10.0.0.8:3306)
The latest slave 10.0.0.18(10.0.0.18:3306) has all relay logs for recovery.
Selected 10.0.0.18(10.0.0.18:3306) as a new master.
10.0.0.18(10.0.0.18:3306): OK: Applying all logs succeeded.
10.0.0.18(10.0.0.18:3306): OK: Activated master IP address.
10.0.0.28(10.0.0.28:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
10.0.0.28(10.0.0.28:3306): OK: Applying all logs succeeded. Slave started, replicating from 10.0.0.18(10.0.0.18:3306)
10.0.0.18(10.0.0.18:3306): Resetting slave info succeeded.
Master failover to 10.0.0.18(10.0.0.18:3306) completed successfully.
Sat Oct 17 16:45:29 2020 - [info] Sending mail..
[1]+ Done masterha_manager --conf=/etc/mastermha/app1.cnf
[root@mha ~]# masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
#验证VIP漂移至新的Master上
[root@Slave1 ~]#ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:27:dd:86 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.18/24 brd 10.0.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 10.0.0.100/24 brd 10.0.0.255 scope global secondary eth0:1
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fe27:dd86/64 scope link
valid_lft forever preferred_lft forever
注意:漂移至新的master主机后,需要修改其原先的配置文件,将read_only设置为read_only=OFF
[root@mha ~]# rm -f /data/mastermha/app1/app1.failover.complete
总结:
需要先修改新master服务器的配置文件,重启服务,这里以slave1(即新master)为例
[root@Slave1 ~]#vim /etc/my.cnf
[mysqld]
server-id=18
log_bin=/data/mysqllogbin/mysql-bin
general_log
#read_only
relay_log_purge=0
datadir=/data/mysql
skip_name_resolve=1
[root@Slave1 ~]#service mysqld restart
(root@localhost) [(none)]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 177 |
| mysql-bin.000002 | 177 |
| mysql-bin.000003 | 177 |
| mysql-bin.000004 | 154 |
+------------------+-----------+
4 rows in set (0.00 sec)
当主服务器宕机后,需要修改原先的master服务器配置文件/etc/my.cnf,将其改为从服务器的配置,重启服务
连接mysql,这里以原有的master为例:
(root@localhost) [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.18',
-> MASTER_USER='bryant',
-> MASTER_PASSWORD='centos',
-> MASTER_LOG_FILE='mysql-bin.000004',
-> MASTER_LOG_POS=154;
(root@localhost) [(none)]> start slave;
原有master服务器配置修改后,还需要新master服务器的配置文件,重启服务
在重启MHA即可
[root@mha ~]# masterha_manager --conf=/etc/mastermha/app1.cnf &
Galera Cluster:集成了Galera插件的MySQL集群,是一种新型的,数据不共享的,高度冗余的高可用方案,目前Galera Cluster有两个版本,分别是Percona Xtradb Cluster及MariaDB Cluster,Galera本身是具有多主特性的,即采用multi-master的集群架构,是一个既稳健,又在数据一致性、完整性及高性能方面有出色表现的高可用解决方案
Galera Cluster特点
Galera Cluster 缺点
Galera Cluster工作过程
Galera Cluster官方文档:
http://galeracluster.com/documentation-webpages/galera-documentation.pdf
http://galeracluster.com/documentation-webpages/index.html
https://www.percona.com/doc/percona-xtradb-cluster/LATEST/index.html
https://mariadb.com/kb/en/library/getting-started-with-mariadb-galera-cluster/
Galera Cluster包括两个组件
Galera replication library (galera-3)
WSREP:MySQL extended with the Write Set Replication
WSREP复制实现:
https://mirrors.tuna.tsinghua.edu.cn/percona/release/$releasever/RPMS/$basearch
https://mirrors.tuna.tsinghua.edu.cn/mariadb/mariadb-5.5.X/yum/centos7-amd64/
注意:两者都需要至少三个节点,不能安装mysql server 或mariadb-server
PXC中涉及到的重要概念和核心参数:
(1)集群中节点的数量:整个集群中节点数量应该控制在最少3个、最多8个的范围内。最少3个节点是为了防止出现脑裂现象,因为只有在2个节点下才会出现此现象。脑裂现象的标志就是输入任何命令,返回的结果都是unknown command。节点在集群中,会因新节点的加入或故障、同步失效等原因发生状态的切换。
(2)节点状态的变化阶段:
备注:donor节点就是数据的贡献者,如果一个新节点加入集群,此时又需要大量数据的SST数据传输,就有可能因此而拖垮整个集群的性能,所以在生产环境中,如果数据量较小,还可以使用SST全量数据传输,但如果数据量很大就不建议使用这种方式,可以考虑先建立主从关系,然后再加入集群。
(3)节点的数据传输方式
1 环境准备:
四台主机:
PXC1:10.0.0.7 CentOS 7
PXC2:10.0.0.17 CentOS 7
PXC3:10.0.0.27 CentOS 7
PXC4:10.0.0.37 CentOS 7
注意:CentOS 8版本目前不支持PXC
关闭防火墙和SELinux,保证时间同步
注意:若已经安装了MySQL,必须卸载
2 安装 Percona XtraDB Cluster 5.7
#此处使用清华大学YUM源
[root@pxc1 ~]# vim /etc/yum.repos.d/pxc.repo
[PXC]
name=percona xtradb cluster
baseurl=https://mirrors.tuna.tsinghua.edu.cn/percona/release/$releasever/RPMS/$basearch
enabled=1
gpgcheck=0
[root@pxc1 ~]# yum repolist
#在pxc1上配置基于key验证
[root@pxc1 ~]# ssh-keygen
[root@pxc1 ~]# ssh-copy-id 127.0.0.1
[root@pxc1 ~]# rsync -a .ssh 10.0.0.17:/root/
[root@pxc1 ~]# rsync -a .ssh 10.0.0.27:/root/
#将YUM源配置文件拷贝至17和27上
[root@pxc1 ~]# scp /etc/yum.repos.d/pxc.repo 10.0.0.17:/etc/yum.repos.d/
[root@pxc1 ~]# scp /etc/yum.repos.d/pxc.repo 10.0.0.27:/etc/yum.repos.d/
#在三个节点上安装PXC 5.7
[root@pxc1 ~]# yum -y install Percona-XtraDB-Cluster-57
[root@pxc2 ~]# yum -y install Percona-XtraDB-Cluster-57
[root@pxc3 ~]# yum -y install Percona-XtraDB-Cluster-57
3 在各个节点上分别配置mysql及集群配置文件
/etc/my.cnf为主配置文件,当前版本中,其余的配置文件都放在/etc/percona-xtradb-cluster.conf.d目录里,包括mysqld.cnf,mysqld_safe.cnf,wsrep.cnf三个文件
#主配置文件不需要修改
[root@pxc1 ~]# cat /etc/my.cnf
#
# The Percona XtraDB Cluster 5.7 configuration file.
#
#
# * IMPORTANT: Additional settings that can override those from this file!
# The files must end with '.cnf', otherwise they'll be ignored.
# Please make any edits and changes to the appropriate sectional files
# included below.
#
!includedir /etc/my.cnf.d/
!includedir /etc/percona-xtradb-cluster.conf.d/
[root@pxc1 ~]# ls /etc/my.cnf.d/
[root@pxc1 ~]# ls /etc/percona-xtradb-cluster.conf.d/
mysqld.cnf mysqld_safe.cnf wsrep.cnf
#修改如下配置文件
# Template my.cnf for PXC
# Edit to your requirements.
[client]
socket=/var/lib/mysql/mysql.sock
[mysqld]
server-id=7 #建议各个节点不同
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin #建议启用
log_slave_updates
expire_logs_days=7
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#下面配置文件不需要修改
[root@pxc1 ~]# cat /etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf
#
# The Percona Server 5.7 configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
#PXC的配置文件必须修改
#在pxc1上
[root@pxc1 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
[root@pxc1 ~]# grep -Ev "^(#|$)" /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.17,10.0.0.27 #三个节点的IP
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=10.0.0.7 #各个节点,指定自己的IP
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-7 #各个节点,指定自己节点名称
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:s3cretPass" #取消本行注释
#在pxc2上
[root@pxc2 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
[root@pxc2 ~]# grep -Ev "^(#|$)" /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.17,10.0.0.27 #三个节点的IP
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=10.0.0.17 #各个节点,指定自己的IP
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-17 #各个节点,指定自己节点名称
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:s3cretPass" #取消本行注释
#在pxc3上
[root@pxc3 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
[root@pxc3 ~]# grep -Ev "^(#|$)" /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.17,10.0.0.27 #三个节点的IP
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=10.0.0.27 #各个节点,指定自己的IP
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-27 #各个节点,指定自己节点名称
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:s3cretPass" #取消本行注释
注意:尽管Galera Cluster不再需要通过binlog的形式进行同步,但还是建议在配置文件中开启二进制日志功能,原因是后期如果有新节点需要加入,老节点通过SST全量传输的方式向新节点传输数据,很可能会拖垮集群性能,所以让新节点先通过binlog方式完成同步后再加入集群会是一种更好的选择
[root@pxc1 ~]# ss -ntul
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:123 *:*
udp UNCONN 0 0 127.0.0.1:323 *:*
udp UNCONN 0 0 [::1]:323 [::]:*
tcp LISTEN 0 100 127.0.0.1:25 *:*
tcp LISTEN 0 128 *:22 *:*
tcp LISTEN 0 100 [::1]:25 [::]:*
tcp LISTEN 0 128 [::]:22 [::]:*
#启动第一个节点
[root@pxc1 ~]# systemctl start [email protected]
[root@pxc1 ~]# ss -ntul
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:123 *:*
udp UNCONN 0 0 127.0.0.1:323 *:*
udp UNCONN 0 0 [::1]:323 [::]:*
tcp LISTEN 0 128 *:4567 *:*
tcp LISTEN 0 100 127.0.0.1:25 *:*
tcp LISTEN 0 128 *:22 *:*
tcp LISTEN 0 100 [::1]:25 [::]:*
tcp LISTEN 0 80 [::]:3306 [::]:*
tcp LISTEN 0 128 [::]:22 [::]:*
#查看root密码
[root@pxc1 ~]# grep "temporary password" /var/log/mysqld.log
2020-10-18T03:38:50.972600Z 1 [Note] A temporary password is generated for root@localhost: 10SughmE;yxP
[root@pxc1 ~]# mysql -uroot -p'10SughmE;yxP'
#修改root密码
mysql> alter user 'root'@'localhost' identified by 'centos';
Query OK, 0 rows affected (0.00 sec)
#创建相关用户并授权
mysql> create user 'sstuser'@'localhost' identified by 's3cretPass';
Query OK, 0 rows affected (0.01 sec)
mysql> grant reload,lock tables,process,replication client on *.* to 'sstuser'@'localhost';
Query OK, 0 rows affected (0.01 sec)
#查看相关变量
mysql> show variables like 'wsrep%'\G
*************************** 1. row ***************************
Variable_name: wsrep_OSU_method
Value: TOI
*************************** 2. row ***************************
Variable_name: wsrep_RSU_commit_timeout
Value: 5000
*************************** 3. row ***************************
Variable_name: wsrep_auto_increment_control
Value: ON
*************************** 4. row ***************************
Variable_name: wsrep_causal_reads
Value: OFF
*************************** 5. row ***************************
Variable_name: wsrep_certification_rules
Value: strict
*************************** 6. row ***************************
Variable_name: wsrep_certify_nonPK
Value: ON
*************************** 7. row ***************************
Variable_name: wsrep_cluster_address
Value: gcomm://10.0.0.7,10.0.0.17,10.0.0.27
*************************** 8. row ***************************
Variable_name: wsrep_cluster_name
Value: pxc-cluster
*************************** 9. row ***************************
Variable_name: wsrep_convert_LOCK_to_trx
Value: OFF
*************************** 10. row ***************************
Variable_name: wsrep_data_home_dir
Value: /var/lib/mysql/
*************************** 11. row ***************************
Variable_name: wsrep_dbug_option
Value:
*************************** 12. row ***************************
Variable_name: wsrep_debug
Value: OFF
*************************** 13. row ***************************
Variable_name: wsrep_desync
Value: OFF
*************************** 14. row ***************************
Variable_name: wsrep_dirty_reads
Value: OFF
*************************** 15. row ***************************
Variable_name: wsrep_drupal_282555_workaround
Value: OFF
*************************** 16. row ***************************
Variable_name: wsrep_forced_binlog_format
Value: NONE
*************************** 17. row ***************************
Variable_name: wsrep_load_data_splitting
Value: ON
*************************** 18. row ***************************
Variable_name: wsrep_log_conflicts
Value: ON
*************************** 19. row ***************************
Variable_name: wsrep_max_ws_rows
Value: 0
*************************** 20. row ***************************
Variable_name: wsrep_max_ws_size
Value: 2147483647
*************************** 21. row ***************************
Variable_name: wsrep_node_address
Value: 10.0.0.7
*************************** 22. row ***************************
Variable_name: wsrep_node_incoming_address
Value: AUTO
*************************** 23. row ***************************
Variable_name: wsrep_node_name
Value: pxc-cluster-node-7
*************************** 24. row ***************************
Variable_name: wsrep_notify_cmd
Value:
*************************** 25. row ***************************
Variable_name: wsrep_on
Value: ON
*************************** 26. row ***************************
Variable_name: wsrep_preordered
Value: OFF
*************************** 27. row ***************************
Variable_name: wsrep_provider
Value: /usr/lib64/galera3/libgalera_smm.so
*************************** 28. row ***************************
Variable_name: wsrep_provider_options
Value: base_dir = /var/lib/mysql/; base_host = 10.0.0.7; base_port = 4567; cert.log_conflicts = no; cert.optimistic_pa = yes; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.info_log_mask = 0; evs.install_timeout = PT7.5S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 10; evs.stats_report_period = PT1M; evs.suspect_timeout = PT5S; evs.use_aggregate = true; evs.user_send_window = 4; evs.version = 0; evs.view_forget_timeout = P1D; gcache.dir = /var/lib/mysql/; gcache.freeze_purge_at_seqno = -1; gcache.keep_pages_count = 0; gcache.keep_pages_size = 0; gcache.mem_size = 0; gcache.name = /var/lib/mysql//galera.cache; gcache.page_size = 128M; gcache.recover = no; gcache.size = 128M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1; gcs.fc_limit = 100; gcs.fc_master_slave = no; gcs
*************************** 29. row ***************************
Variable_name: wsrep_recover
Value: OFF
*************************** 30. row ***************************
Variable_name: wsrep_reject_queries
Value: NONE
*************************** 31. row ***************************
Variable_name: wsrep_replicate_myisam
Value: OFF
*************************** 32. row ***************************
Variable_name: wsrep_restart_slave
Value: OFF
*************************** 33. row ***************************
Variable_name: wsrep_retry_autocommit
Value: 1
*************************** 34. row ***************************
Variable_name: wsrep_slave_FK_checks
Value: ON
*************************** 35. row ***************************
Variable_name: wsrep_slave_UK_checks
Value: OFF
*************************** 36. row ***************************
Variable_name: wsrep_slave_threads
Value: 8
*************************** 37. row ***************************
Variable_name: wsrep_sst_auth
Value: ********
*************************** 38. row ***************************
Variable_name: wsrep_sst_donor
Value:
*************************** 39. row ***************************
Variable_name: wsrep_sst_donor_rejects_queries
Value: OFF
*************************** 40. row ***************************
Variable_name: wsrep_sst_method
Value: xtrabackup-v2
*************************** 41. row ***************************
Variable_name: wsrep_sst_receive_address
Value: AUTO
*************************** 42. row ***************************
Variable_name: wsrep_start_position
Value: 00000000-0000-0000-0000-000000000000:-1
*************************** 43. row ***************************
Variable_name: wsrep_sync_wait
Value: 0
43 rows in set (0.01 sec)
#查看相关状态变量
mysql> show status like 'wsrep%'\G
*************************** 1. row ***************************
Variable_name: wsrep_local_state_uuid
Value: 75d0cf66-10f3-11eb-a779-0b042f3373cf
*************************** 2. row ***************************
Variable_name: wsrep_protocol_version
Value: 9
*************************** 3. row ***************************
Variable_name: wsrep_last_applied
Value: 3
*************************** 4. row ***************************
Variable_name: wsrep_last_committed
Value: 3
*************************** 5. row ***************************
Variable_name: wsrep_replicated
Value: 3
*************************** 6. row ***************************
Variable_name: wsrep_replicated_bytes
Value: 752
*************************** 7. row ***************************
Variable_name: wsrep_repl_keys
Value: 3
*************************** 8. row ***************************
Variable_name: wsrep_repl_keys_bytes
Value: 96
*************************** 9. row ***************************
Variable_name: wsrep_repl_data_bytes
Value: 460
*************************** 10. row ***************************
Variable_name: wsrep_repl_other_bytes
Value: 0
*************************** 11. row ***************************
Variable_name: wsrep_received
Value: 2
*************************** 12. row ***************************
Variable_name: wsrep_received_bytes
Value: 150
*************************** 13. row ***************************
Variable_name: wsrep_local_commits
Value: 0
*************************** 14. row ***************************
Variable_name: wsrep_local_cert_failures
Value: 0
*************************** 15. row ***************************
Variable_name: wsrep_local_replays
Value: 0
*************************** 16. row ***************************
Variable_name: wsrep_local_send_queue
Value: 0
*************************** 17. row ***************************
Variable_name: wsrep_local_send_queue_max
Value: 1
*************************** 18. row ***************************
Variable_name: wsrep_local_send_queue_min
Value: 0
*************************** 19. row ***************************
Variable_name: wsrep_local_send_queue_avg
Value: 0.000000
*************************** 20. row ***************************
Variable_name: wsrep_local_recv_queue
Value: 0
*************************** 21. row ***************************
Variable_name: wsrep_local_recv_queue_max
Value: 2
*************************** 22. row ***************************
Variable_name: wsrep_local_recv_queue_min
Value: 0
*************************** 23. row ***************************
Variable_name: wsrep_local_recv_queue_avg
Value: 0.500000
*************************** 24. row ***************************
Variable_name: wsrep_local_cached_downto
Value: 1
*************************** 25. row ***************************
Variable_name: wsrep_flow_control_paused_ns
Value: 0
*************************** 26. row ***************************
Variable_name: wsrep_flow_control_paused
Value: 0.000000
*************************** 27. row ***************************
Variable_name: wsrep_flow_control_sent
Value: 0
*************************** 28. row ***************************
Variable_name: wsrep_flow_control_recv
Value: 0
*************************** 29. row ***************************
Variable_name: wsrep_flow_control_interval
Value: [ 100, 100 ]
*************************** 30. row ***************************
Variable_name: wsrep_flow_control_interval_low
Value: 100
*************************** 31. row ***************************
Variable_name: wsrep_flow_control_interval_high
Value: 100
*************************** 32. row ***************************
Variable_name: wsrep_flow_control_status
Value: OFF
*************************** 33. row ***************************
Variable_name: wsrep_cert_deps_distance
Value: 1.000000
*************************** 34. row ***************************
Variable_name: wsrep_apply_oooe
Value: 0.000000
*************************** 35. row ***************************
Variable_name: wsrep_apply_oool
Value: 0.000000
*************************** 36. row ***************************
Variable_name: wsrep_apply_window
Value: 1.000000
*************************** 37. row ***************************
Variable_name: wsrep_commit_oooe
Value: 0.000000
*************************** 38. row ***************************
Variable_name: wsrep_commit_oool
Value: 0.000000
*************************** 39. row ***************************
Variable_name: wsrep_commit_window
Value: 1.000000
*************************** 40. row ***************************
Variable_name: wsrep_local_state
Value: 4
*************************** 41. row ***************************
Variable_name: wsrep_local_state_comment
Value: Synced
*************************** 42. row ***************************
Variable_name: wsrep_cert_index_size
Value: 1
*************************** 43. row ***************************
Variable_name: wsrep_cert_bucket_count
Value: 22
*************************** 44. row ***************************
Variable_name: wsrep_gcache_pool_size
Value: 2192
*************************** 45. row ***************************
Variable_name: wsrep_causal_reads
Value: 0
*************************** 46. row ***************************
Variable_name: wsrep_cert_interval
Value: 0.000000
*************************** 47. row ***************************
Variable_name: wsrep_open_transactions
Value: 0
*************************** 48. row ***************************
Variable_name: wsrep_open_connections
Value: 0
*************************** 49. row ***************************
Variable_name: wsrep_ist_receive_status
Value:
*************************** 50. row ***************************
Variable_name: wsrep_ist_receive_seqno_start
Value: 0
*************************** 51. row ***************************
Variable_name: wsrep_ist_receive_seqno_current
Value: 0
*************************** 52. row ***************************
Variable_name: wsrep_ist_receive_seqno_end
Value: 0
*************************** 53. row ***************************
Variable_name: wsrep_incoming_addresses
Value: 10.0.0.7:3306
*************************** 54. row ***************************
Variable_name: wsrep_cluster_weight
Value: 1
*************************** 55. row ***************************
Variable_name: wsrep_desync_count
Value: 0
*************************** 56. row ***************************
Variable_name: wsrep_evs_delayed
Value:
*************************** 57. row ***************************
Variable_name: wsrep_evs_evict_list
Value:
*************************** 58. row ***************************
Variable_name: wsrep_evs_repl_latency
Value: 0/0/0/0/0
*************************** 59. row ***************************
Variable_name: wsrep_evs_state
Value: OPERATIONAL
*************************** 60. row ***************************
Variable_name: wsrep_gcomm_uuid
Value: 75cf9a49-10f3-11eb-b47a-32eb282ca67d
*************************** 61. row ***************************
Variable_name: wsrep_cluster_conf_id
Value: 1
*************************** 62. row ***************************
Variable_name: wsrep_cluster_size
Value: 1
*************************** 63. row ***************************
Variable_name: wsrep_cluster_state_uuid
Value: 75d0cf66-10f3-11eb-a779-0b042f3373cf
*************************** 64. row ***************************
Variable_name: wsrep_cluster_status
Value: Primary
*************************** 65. row ***************************
Variable_name: wsrep_connected
Value: ON
*************************** 66. row ***************************
Variable_name: wsrep_local_bf_aborts
Value: 0
*************************** 67. row ***************************
Variable_name: wsrep_local_index
Value: 0
*************************** 68. row ***************************
Variable_name: wsrep_provider_name
Value: Galera
*************************** 69. row ***************************
Variable_name: wsrep_provider_vendor
Value: Codership Oy
*************************** 70. row ***************************
Variable_name: wsrep_provider_version
Value: 3.45(ra60e019)
*************************** 71. row ***************************
Variable_name: wsrep_ready
Value: ON
71 rows in set (0.01 sec)
#重点关注下面内容
mysql> show status like 'wsrep%';
+----------------------------------+--------------------------------------+
| Variable_name | Value |
+----------------------------------+--------------------------------------+
| wsrep_local_state_uuid | 75d0cf66-10f3-11eb-a779-0b042f3373cf |
...
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
...
| wsrep_cluster_size | 1 |
| wsrep_cluster_state_uuid | 75d0cf66-10f3-11eb-a779-0b042f3373cf |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
...
| wsrep_ready | ON |
+----------------------------------+--------------------------------------+
说明:
wresp_cluster_size表示,该Galera集群中只有一个节点
wsrep_local_state_comment 状态为Synced(4),表示数据已同步完成(因为是第一个引导节点,无数据需要同步)。如果状态是Joiner,意味着SST没有完成,只有所有节点状态时Synced,才可以加新节点
wsrep_cluster_status为Primary,且已经完全连接并准备好
5 启动PXC集群中其它所有节点
#在pxc2上
[root@pxc2 ~]# ss -ntul
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:123 *:*
udp UNCONN 0 0 127.0.0.1:323 *:*
udp UNCONN 0 0 [::1]:323 [::]:*
tcp LISTEN 0 100 127.0.0.1:25 *:*
tcp LISTEN 0 128 *:22 *:*
tcp LISTEN 0 100 [::1]:25 [::]:*
tcp LISTEN 0 128 [::]:22 [::]:*
[root@pxc2 ~]# systemctl start mysql
[root@pxc2 ~]# ss -ntulp
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:123 *:* users:(("chronyd",pid=711,fd=7))
udp UNCONN 0 0 127.0.0.1:323 *:* users:(("chronyd",pid=711,fd=5))
udp UNCONN 0 0 [::1]:323 [::]:* users:(("chronyd",pid=711,fd=6))
tcp LISTEN 0 128 *:4567 *:* users:(("mysqld",pid=3963,fd=11))
tcp LISTEN 0 100 127.0.0.1:25 *:* users:(("master",pid=2144,fd=13))
tcp LISTEN 0 128 *:22 *:* users:(("sshd",pid=948,fd=3))
tcp LISTEN 0 100 [::1]:25 [::]:* users:(("master",pid=2144,fd=14))
tcp LISTEN 0 80 [::]:3306 [::]:* users:(("mysqld",pid=3963,fd=33))
tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=948,fd=4))
#在pcx3上
[root@pxc3 ~]# ss -ntul
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:123 *:*
udp UNCONN 0 0 127.0.0.1:323 *:*
udp UNCONN 0 0 [::1]:323 [::]:*
tcp LISTEN 0 100 127.0.0.1:25 *:*
tcp LISTEN 0 128 *:22 *:*
tcp LISTEN 0 100 [::1]:25 [::]:*
tcp LISTEN 0 128 [::]:22 [::]:*
[root@pxc3 ~]# systemctl start mysql
[root@pxc3 ~]# ss -ntulp
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:123 *:* users:(("chronyd",pid=719,fd=7))
udp UNCONN 0 0 127.0.0.1:323 *:* users:(("chronyd",pid=719,fd=5))
udp UNCONN 0 0 [::1]:323 [::]:* users:(("chronyd",pid=719,fd=6))
tcp LISTEN 0 128 *:4567 *:* users:(("mysqld",pid=4287,fd=11))
tcp LISTEN 0 100 127.0.0.1:25 *:* users:(("master",pid=2497,fd=13))
tcp LISTEN 0 128 *:22 *:* users:(("sshd",pid=954,fd=3))
tcp LISTEN 0 100 [::1]:25 [::]:* users:(("master",pid=2497,fd=14))
tcp LISTEN 0 80 [::]:3306 [::]:* users:(("mysqld",pid=4287,fd=34))
tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=954,fd=4))
6 查看集群状态,验证集群是否成功
#在任意节点,查看集群状态
[root@pxc2 ~]# mysql -uroot -pcentos
mysql> show variables like 'wsrep_node_name';
+-----------------+---------------------+
| Variable_name | Value |
+-----------------+---------------------+
| wsrep_node_name | pxc-cluster-node-17 |
+-----------------+---------------------+
1 row in set (0.01 sec)
mysql> show variables like 'wsrep_node_address';
+--------------------+-----------+
| Variable_name | Value |
+--------------------+-----------+
| wsrep_node_address | 10.0.0.17 |
+--------------------+-----------+
1 row in set (0.00 sec)
mysql> show variables like 'wsrep_on';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wsrep_on | ON |
+---------------+-------+
1 row in set (0.00 sec)
mysql> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| wsrep_cluster_size | 3 |
+--------------------+-------+
1 row in set (0.01 sec)
#在任意节点查看数据库
mysql> create database db1;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
#在其它任意节点验证数据是否同步
[root@pxc3 ~]# mysql -uroot -pcentos
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
#利用Xshell软件,同时在三个节点创建数据库db2,在其中一个节点成功
mysql> create database db2;
Query OK, 1 row affected (0.03 sec)
#在其它节点都提示失败
mysql> create database db2;
ERROR 1007 (HY000): Can't create database 'db2'; database exists
7 在PXC集群中加入节点
一个节点加入到Galera集群有两种情况:新节点加入集群,暂时离组的成员再次加入集群
1)新节点加入Galera集群
新节点加入集群时,需要从当前集群中选择一个Donor节点来同步数据,也就是所谓的state_snapshot_transfer(SST)过程。SST同步数据的方式由选项wsrep_sst_method决定,一般选择的是xtrabackup。
必须注意,新节点加入Galera时,会删除新节点上所有已有数据,再通过xtrabackup(假设使用的是该方式)从Donor处完整备份所有数据进行恢复,所以,如果数据量很大,新节点加入过程会很慢。而且,在一个新节点成为Synced状态之前,不要同时加入其它新节点,否则很容易将集群压垮。
如果是这种情况,可以考虑使用wsrep_sst_method=rsync来做增量同步,既然是增量同步,最好保证新结点上已经有一部分数据基础,否则和全量同步没什么区别,且这样会对Donor节点加上全局read only锁。
2)旧节点加入Galera集群
如果旧节点加入Galera集群,说明这个节点在之前就已经在Galera集群中呆过,有一部分数据基础,缺少的只是它离开集群时的数据。这时加入集群时,会采用IST(Incremental Snapshot Transfer)传输机制,即使用增量传输。
但注意,这部分增量数据的数据源是Donor上缓存在GCache文件中的,这个文件有大小限制,如果缺失的数据范围超过已缓存的内容,则自动转为SST传输。如果旧节点上的数据和Donor上的数据不匹配(例如这个节点离组后人为修改了一点数据),则自动转为SST传输。
#在PXC集群中再加一台新的主机PXC4: 10.0.0.37
[root@pxc4 ~]# vim /etc/yum.repos.d/pxc.repo
[PXC]
name=percona xtradb cluster
baseurl=https://mirrors.tuna.tsinghua.edu.cn/percona/release/$releasever/RPMS/$basearch
enabled=1
gpgcheck=0
[root@pxc4 ~]# yum repolist
[root@pxc4 ~]# yum -y install Percona-XtraDB-Cluster-57
[root@pxc4 ~]# grep -Ev "^(#|$)" /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.17,10.0.0.27,10.0.0.37
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=10.0.0.37
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-37
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:s3cretPass"
[root@pxc4 ~]# systemctl start mysql
[root@pxc4 ~]# mysql -uroot -pcentos
mysql> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| wsrep_cluster_size | 4 |
+--------------------+-------+
1 row in set (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
#将其他节点的配置文件加以修改,主要是添加新加节点的IP地址
[root@pxc1 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.17,10.0.0.27,10.0.0.37
[root@pxc2 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.17,10.0.0.27,10.0.0.37
[root@pxc3 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.17,10.0.0.27,10.0.0.37
8 在PXC集群中修复故障节点
#在任意节点停止服务
[root@pxc3 ~]# systemctl stop mysql
#在任意节点上查看wsrep_cluster_size变量少了一个节点
[root@pxc4 ~]# mysql -uroot -pcentos
mysql> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| wsrep_cluster_size | 3 |
+--------------------+-------+
1 row in set (0.00 sec)
mysql> create database db3;
Query OK, 1 row affected (0.01 sec)
#在其它任意节点可看到数据已同步
[root@pxc1 ~]# mysql -uroot -pcentos
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| db3 |
| mysql |
| performance_schema |
| sys |
+--------------------+
7 rows in set (0.00 sec)
#恢复服务,数据同步
[root@pxc3 ~]# systemctl start mysql
[root@pxc3 ~]# mysql -uroot -pcentos
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| db3 |
| mysql |
| performance_schema |
| sys |
+--------------------+
7 rows in set (0.00 sec)
mysql> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| wsrep_cluster_size | 4 |
+--------------------+-------+
1 row in set (0.02 sec)
范例: 在centos8上实现MariaDB Garera Cluster
#在三个节点上都实现
#在MGC1上
[root@MGC1 ~]#yum -y install mariadb-server-galera
[root@MGC1 ~]#vim /etc/my.cnf.d/galera.cnf
#wsrep_cluster_address="dummy://"
wsrep_cluster_address="dummy://10.0.0.8,10.0.0.18,10.0.0.28"
#在MGC2上
[root@MGC2 ~]#yum -y install mariadb-server-galera
[root@MGC2 ~]#vim /etc/my.cnf.d/galera.cnf
#wsrep_cluster_address="dummy://"
wsrep_cluster_address="dummy://10.0.0.8,10.0.0.18,10.0.0.28"
#在MGC3上
[root@MGC3 ~]#yum -y install mariadb-server-galera
[root@MGC3 ~]#vim /etc/my.cnf.d/galera.cnf
#wsrep_cluster_address="dummy://"
wsrep_cluster_address="dummy://10.0.0.8,10.0.0.18,10.0.0.28"
#启动第一节点
[root@MGC1 ~]#galera_new_cluster
[root@MGC1 ~]#ss -ntul
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 127.0.0.1:323 0.0.0.0:*
udp UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
udp UNCONN 0 0 [::1]:323 [::]:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:4567 0.0.0.0:*
tcp LISTEN 0 100 127.0.0.1:25 0.0.0.0:*
tcp LISTEN 0 80 0.0.0.0:3306 0.0.0.0:*
tcp LISTEN 0 128 [::]:22 [::]:*
tcp LISTEN 0 100 [::1]:25 [::]:*
#再启动其它节点
#在MGC2上
[root@MGC2 ~]#systemctl enable --now mariadb
[root@MGC2 ~]#ss -ntul
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 127.0.0.1:323 0.0.0.0:*
udp UNCONN 0 0 [::1]:323 [::]:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:4567 0.0.0.0:*
tcp LISTEN 0 80 0.0.0.0:3306 0.0.0.0:*
tcp LISTEN 0 128 [::]:22 [::]:*
#在MGC3上
[root@MGC3 ~]#systemctl enable --now mariadb
[root@MGC3 ~]#[root@centos8 ~]#ss -ntul
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 127.0.0.1:323 0.0.0.0:*
udp UNCONN 0 0 [::1]:323 [::]:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:4567 0.0.0.0:*
tcp LISTEN 0 80 0.0.0.0:3306 0.0.0.0:*
tcp LISTEN 0 128 [::]:22 [::]:*
[root@MGC3 ~]#[mysql
MariaDB [(none)]> show status like 'wsrep_ready';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wsrep_ready | ON |
+---------------+-------+
1 row in set (0.001 sec)
MariaDB [(none)]> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| wsrep_cluster_size | 3 |
+--------------------+-------+
1 row in set (0.001 sec)
MariaDB [(none)]> SHOW VARIABLES LIKE 'wsrep_%'\G
MariaDB [(none)]> SHOW STATUS LIKE 'wsrep_%';
范例: CentOS 7上实现MariaDB Galera Cluster 5.5
#参考仓库:https://mirrors.tuna.tsinghua.edu.cn/mariadb/mariadb-5.5.X/yum/centos7-
amd64/
yum install MariaDB-Galera-server
vim /etc/my.cnf.d/server.cnf
[galera]
wsrep_provider = /usr/lib64/galera/libgalera_smm.so
wsrep_cluster_address="gcomm://10.0.0.7,10.0.0.17,10.0.0.27"
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0
#下面配置可选项
wsrep_cluster_name = 'mycluster' 默认my_wsrep_cluster
wsrep_node_name = 'node1'
wsrep_node_address = '10.0.0.7'
#首次启动时,需要初始化集群,在其中一个节点上执行命令
/etc/init.d/mysql start --wsrep-new-cluster
#而后正常启动其它节点
service mysql start
#查看集群中相关系统变量和状态变量
SHOW VARIABLES LIKE 'wsrep_%';
SHOW STATUS LIKE 'wsrep_%';
SHOW STATUS LIKE 'wsrep_cluster_size';
TiDB 是 PingCAP 公司受 Google Spanner / F1 论文启发而设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和NoSQL 的最佳特性。
TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB和mysql几乎完全兼容
TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。TiDB年可用性达到99.95%
TiDB 的目标是为 OLTP(Online Transactional Processing) 和 OLAP (Online Analytical Processing) 场
景提供一站式的解决方案。
TiDB Server
TiDB Server 负责接收SQL请求,处理SQL相关的逻辑,并通过PD找到存储计算所需数据的TiKV地址,与TiKV交互获取数据,最终返回结果。TiDB Server 是无状态的,其本身并不存储数据,只负责计算,可以无限水平扩展,可以通过负载均衡组件(LVS、HAProxy或F5)对外提供统一的接入地址。
PD Server
Placement Driver(简称PD)是整个集群的管理模块,其主要工作有三个:一是存储集群的元信息(某个Key存储在那个TiKV节点);二是对TiKV集群进行调度和负载均衡(如数据的迁移、Raft group leader的迁移等);三是分配全局唯一且递增的事务ID
PD 是一个集群,需要部署奇数个节点,一般线上推荐至少部署3个节点。PD在选举的过程中无法对外提供服务,这个时间大约是3秒
TiKV Server
TiKV Server 负责存储数据,从外部看TiKV是一个分布式的提供事务的Key-Value存储引擎。存储数据的基本单位是Region,每个Region负责存储一个Key Range(从StartKey到EndKey的左闭右开区间)的数据,每个TiKV节点会负责多个Region。TiKV使用Raft协议做复制,保持数据的一致性和容灾。副本以
Region为单位进行管理,不同节点上的多个Region构成一个Raft Group,互为副本。数据在多个TiKV之间的负载均衡由PD调度,这里也就是以Region为单位进行调度