Mysql集群笔记
概述
我们在考虑 MySQL 数据库的高可用的架构时,主要要考虑如下几方面:
-
如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中断
-
用作备份、只读副本等功能的非主节点的数据应该和主节点的数据实时或者最终保持一致
-
当业务发生数据库切换时,切换前后的数据库内容应当一致,不会因为数据缺失或者数据不一致而影响业务
*Mysql集群优劣势
优势
-
高可用性:故障检测及迁移,多节点备份
-
可伸缩性:新增数据库节点便利,方便扩容
-
负载均衡:切换某服务访问某节点,分摊单个节点的数据库压力
劣势
-
从库要从 binlog 获取数据并重放,这肯定与主库写入数据存在时间延迟,因此从库的数据总是要滞后主库
-
对主库与从库之间的网络延迟要求较高,若网络延迟太高,将加重上述的滞后,造成最终数据的不一致
-
单一的主节点挂了,将不能对外提供写服务
集群要考虑的风险
-
网络分裂:群集还可能由于网络故障而拆分为多个部分,每部分内的节点相互连接,但各部分之间的节点失去连接
-
脑裂:导致数据库节点彼此独立运行的集群故障称为 “脑裂”。这种情况可能导致数据不一致,并且无法修复,例如当两个数据库节点独立更新同一表上的同一行时
原理图示
集群类型:
-
M //单主
-
M-S //一主一从
-
M-S-S... //一主多从
-
M-M //双主
-
M-M-S-S //双主双从
图示:一主三从
*原理介绍:
从主库上把数据更改,记录到二进制日志文件(Bin Log)中,从库的I/O线程将主库的二进制日志文件复制到自己的中继日志(Relay Log)中,从库SQL线程读取中继日志中的事件,将中继日志事件重放到从数据库上
集群搭建
环境准备
-
全新服务器-互相通信
-
服务器部署ysql5.7
-
配置域名解析
重新安装多台数据库,不要克隆已经安装的数据库因为数据库的ID相同
Master1 | 192.168.23.19 | systemctl start mysqld |
---|---|---|
Master1 | 192.168.23.20 | systemctl start mysqld |
Slave1 | 192.168.23.21 | systemctl start mysqld |
Slave2 | 192.168.23.22 | systemctl start mysqld |
h3交换机地址 192.168.51.254 admin/P@ssw0rd 默认22端口 ssh可以访问
一主一从
主服务器配置
准备数据(验证主从同步使用)
mysql> create database master1db;
Query OK, 1 row affected (0.01 sec)
mysql> create table master1db.master1tab(name char(50));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into master1db.master1tab values (1111);
Query OK, 1 row affected (0.07 sec)
mysql> insert into master1db.master1tab values (2222);
Query OK, 1 row affected (0.00 sec)
//开启二进制日志文件
[root@bogon ~] vi /etc/my.cnf //编辑Mysql主配置文件添加如下内容
log_bin
server-id=1 //Mysql ID
[root@bogon ~] systemctl restart mysqld //重启Mysql 配置文件生效
[root@bogon ~] ls /var/lib/mysql //查看是否带有bin的文件产生
auto.cnf ca-key.pem client-key.pem ib_logfile0 master1db mysql.sock.lock public_key.pem sys
bogon-bin.000001 ca.pem ib_buffer_pool ib_logfile1 mysql performance_schema server-cert.pem
bogon-bin.index client-cert.pem ibdata1 ibtmp1 mysql.sock private_key.pem server-key.pem
mysql> grant replication slave, replication client on *.* to 'rep'@'192.168.23.%' identified by 'P@ssw0rd1234'; //创建复制用户
[root@bogon ~] mysqldump -pP@ssw0rd1234 --all-databases --single-transaction --master-data=2 --flush-logs > `date +%F`-mysql-all.sql //备份master数据
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@bogon ~] ls //查看是否备份成功
2022-10-28-mysql-all.sql
[root@bogon ~] scp -r 2022-10-28-mysql-all.sql master2:/tmp //把备份文件拷贝到从服务器的/tmp目录下
[root@bogon ~] vi /tmp/2022-10-28-mysql-all.sql //观察二进制日志文件分割点
CHANGE MASTER TO MASTER_LOG_FILE='bogon-bin.000002', MASTER_LOG_POS=154; //bogon-bin.000002 分割点为154
//再次往主数据库上插入数据(验证主从同步使用)
mysql> insert into master1db.master1tab values (33333333);
Query OK, 1 row affected (0.02 sec)
mysql> insert into master1db.master1tab values (44444);
Query OK, 1 row affected (0.00 sec)
那么这次插入的数据没有进行备份,如果主从搭建完成之后怎么才会把这次数据也叫从数据库复制一份呢
从服务器配置
[root@bogon ~] mysql -h master1 -urep -p'P@ssw0rd1234' //测试在主数据库上创建的备份rep用户是否可以通过从服务器进行登陆
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.40-log MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> //成功
[root@bogon ~] vi /etc/my.cnf //这里不用在从设备上开启二进制日志,没有人向master2请求日志,直接指定服务器序号即可
server-id=2 //服务器ID是必须设置的
[root@bogon ~] systemctl restart mysqld //重启使配置文件生效
[root@bogon ~] mysql -uroot -pP@ssw0rd1234 //测试服务器是否修改正确。能否正常登陆
//手动同步数据
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.01 sec)
mysql> source /tmp/2022-10-28-mysql-all.sql
Query OK, 0 rows affected (0.00 sec)
mysql> select * from master1tab;
+------+
| name |
+------+
| 1111 |
| 2222 |
+------+
2 rows in set (0.00 sec) //可以看到最开始的数据已经备份过来了,但是后来又插入的数据怎么备份过来呢?
//设置主服务器
mysql> change master to
master_host='master1',
master_user='rep',
master_password='P@ssw0rd1234',
master_log_file='bogon-bin.000002',
master_log_pos=154; //这里注意,二进制日志的位置,应该参照主服务器备份时生成的新位置
//启动从服务器
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
//查看启动状态
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master1 //主人是谁
Master_User: rep //用户是什么
Master_Port: 3306 //端口是什么
Connect_Retry: 60
Master_Log_File: bogon-bin.000002 //使用是哪个二进制日志文件
Read_Master_Log_Pos: 689
Relay_Log_File: bogon-relay-bin.000002 //中继日志是哪个
Relay_Log_Pos: 855
Relay_Master_Log_File: bogon-bin.000002
Slave_IO_Running: Yes //重点 如果说这个为NO需要检查是否以上配置出错
Slave_SQL_Running: Yes //重点 如果说这个为NO需要检查是否以上配置出错
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: 689
Relay_Log_Space: 1062
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: 1
Master_UUID: 965d58b6-5685-11ed-9000-000c29bc8700
Master_Info_File: /var/lib/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)
mysql> select * from master1tab; //这里可以看到最后插入的数据也成功复制进来了
+----------+
| name |
+----------+
| 1111 |
| 2222 |
| 33333333 |
| 44444 |
+----------+
4 rows in set (0.00 sec)
//在主服务插入数据看是否同步
mysql> insert into master1db.master1tab values (88888);
Query OK, 1 row affected (0.00 sec)
mysql> insert into master1db.master1tab values (80000);
Query OK, 1 row affected (0.00 sec)
//从服务器查看
mysql> select * from master1tab;
+----------+
| name |
+----------+
| 1111 |
| 2222 |
| 33333333 |
| 44444 |
| 88888 |
| 80000 |
+----------+
6 rows in set (0.00 sec)
一主一从GTID
与上一个实验需求基本相同经,master1 作为主mysql,master2 作为从mysql不同之处,使用了“gtid_mode=ON enforce_gtid_consistency=1”该属性自动记录position位置。不需要手动指定了。
-
如果是全新服务器需要按照上一个实验进行主服务器重新配置
//重置从数据库
[root@master2 ~] systemctl stop mysqld
[root@master2 ~] rm -rf /var/lib/mysql/*
[root@master2 ~] systemctl start mysqld
[root@master2 ~] grep password /var/log/mysqld.log
2022-11-01T06:03:20.619010Z 1 [Note] A temporary password is generated for root@localhost: a7tw*gXyRl<w
[root@master2 ~] mysqladmin -uroot -p'a7tw*gXyRl<w' password P@ssw0rd1234
[root@master2 ~] mysql -uroot -pP@ssw0rd1234
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.40 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
主服务器配置
[root@master1 ~] vi /etc/my.cnf //添加如下内容
log_bin
server-id=1
gtid_mode=ON
enforce_gtid_consistency=1
[root@master1 ~] systemctl restart mysqld //重启生效
//添加授权用户,如果有的话则不需要再次添加
mysql>grant replication slave,replication client on *.* to 'rep'@'192.168.122.%' identified by 'QianFeng@123';
mysql>flush privileges;
//备份数据
[root@master1 ~] mysqldump -pP@ssw0rd1234 --all-databases --single-transaction --master-data=2 --flush-logs > `date +%F`-mysql.sql
//模拟数据变化
mysql> insert into master1tab values (888888888888888);
Query OK, 1 row affected (0.00 sec)
从服务器配置
[root@master2 ~] mysql -h master1 -urep -pP@ssw0rd1234 //测试rep用户是否可用
[root@master2 ~] vi /etc/my.cnf //启动二进制日志,服务器ID,GTID,添加如下内容
log_bin
server-id=2
gtid_mode=ON
enforce_gtid_consistency=1
[root@master2 ~] systemctl restart mysqld //重启生效
//手动恢复数据
mysql>set sql_log_bin=0;
mysql> source /tmp/2022-11-01-mysql.sql
mysql>select * from master1db.master1tab;
//设置主服务器
mysql> change master to master_host='master1',master_user='rep',master_password='P@ssw0rd1234',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> start slave; //启动奴隶模式
Query OK, 0 rows affected (0.00 sec)
//返回主服务器(master1)更新数据,在从服务器(master2)观察是否同步。
mysql> insert into master1db.master1tab values (777777777777777777777777777);
Query OK, 1 row affected (0.00 sec)
//从服务器查看
mysql> select * from master1db.master1tab;
+-----------------------------+
| name |
+-----------------------------+
| 1111 |
| 2222 |
| 33333333 |
| 44444 |
| 88888 |
| 80000 |
| 111111111111111 |
| 1988888 |
| 9999999 |
| 888888888888888 |
| 777777777777777777777777777 |
+-----------------------------+
11 rows in set (0.00 sec)
双主双从
双主
前面配置如果出现主服务器但节点故障那么会影响全局的写入事件,所以搭配双主
目前master1(192.168.23.19)是我们的主服务器,这里打算把master2(192.168.23.20)也配置成主服务器实现互相读写
//master2配置
mysql> grant replication slave, replication client on *.* to 'rep'@'192.168.23.%' identified by 'P@ssw0rd1234';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
//master1配置
mysql> change master to master_host='master2',master_user='rep',master_password='P@ssw0rd1234',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G //查看是否正常
master1上插入数据,在master2上观察
mysql> insert into master1tab values (90909090); //master1插入数据
Query OK, 1 row affected (0.00 sec)
mysql> select * from master1tab; //master2查看
+-----------------------------+
| name |
+-----------------------------+
| 1111 |
| 2222 |
| 33333333 |
| 44444 |
| 88888 |
| 80000 |
| 111111111111111 |
| 1988888 |
| 9999999 |
| 888888888888888 |
| 777777777777777777777777777 | |
| 90909090 |
+-----------------------------+
13 rows in set (0.00 sec)
master2上插入数据,在master1上观察
mysql> insert into master1tab values (1010101010); //master2插入数据
Query OK, 1 row affected (0.01 sec)
mysql> select * from master1tab; //master1查看
+-----------------------------+
| name |
+-----------------------------+
| 1111 |
| 2222 |
| 33333333 |
| 44444 |
| 88888 |
| 80000 |
| 111111111111111 |
| 1988888 |
| 9999999 |
| 888888888888888 |
| 777777777777777777777777777
| 90909090
| 1010101010
双方同步成功,双主设置完成。
双从
同步现有的数据库
[root@master1 ~] mysqldump -pP@ssw0rd1234 --all-databases --single-transaction --master-data=2 --flush-logs > `date +%F`-msyql-all-slave.sql //备份主服务器数据得到 2022-11-01-msyql-all-slave.sql文件
mysqldump: [Warning] Using a password on the command line interface can be insecure.
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events.
[root@master1 ~] scp 2022-11-01-msyql-all-slave.sql root@slave1:/tmp //分别把备份文件拷贝到slave1服务器上以及slave2服务器上
[root@master1 ~] scp 2022-11-01-msyql-all-slave.sql root@slave2:/tmp
[root@slave1 ~] mysql -pP@ssw0rd1234 < /tmp/2022-11-01-msyql-all-slave.sql //slave1操作把备份文件写到数据库里
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@slave2 ~] mysql -pP@ssw0rd1234 < /tmp/2022-11-01-msyql-all-slave.sql //slave2操作把备份文件写到数据库里
mysql: [Warning] Using a password on the command line interface can be insecure.
启动从服务器ID,GTID
[root@slave1 ~] vi /etc/my.cnf //slave1服务器添加如下配置
server-id=3
gtid_mode=ON
enforce_gtid_consistency=1
master-info-repository=TABLE
relay-log-info-repository=TABLE
[root@slave2 ~] vi /etc/my.cnf //slave2服务器添加如下配置
server-id=4
gtid_mode=ON
enforce_gtid_consistency=1
master-info-repository=TABLE
relay-log-info-repository=TABLE
[root@slave2 ~] systemctl restart mysqld //重启Mysql服务使其生效
设置主服务器
//slave1服务器操作
mysql> change master to master_host='master1',master_user='rep',master_password='P@ssw0rd1234',master_auto_position=1 for channel 'master1';
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> change master to master_host='master2',master_user='rep',master_password='P@ssw0rd1234',master_auto_position=1 for channel 'master2';
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master1
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master1-bin.000007
Read_Master_Log_Pos: 194
Relay_Log_File: slave1-relay-bin-master1.000002
Relay_Log_Pos: 371
Relay_Master_Log_File: master1-bin.000007
Slave_IO_Running: Yes //正常
Slave_SQL_Running: Yes //正常
*************************** 2. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master2
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master2-bin.000001
Read_Master_Log_Pos: 1211
Relay_Log_File: slave1-relay-bin-master2.000002
Relay_Log_Pos: 420
Relay_Master_Log_File: master2-bin.000001
Slave_IO_Running: Yes //正常
Slave_SQL_Running: Yes //正常
//slave2服务器操作
mysql> change master to master_host='master1',master_user='rep',master_password='P@ssw0rd1234',master_auto_position=1 for channel 'master1';
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> change master to master_host='master2',master_user='rep',master_password='P@ssw0rd1234',master_auto_position=1 for channel 'master2';
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master1
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master1-bin.000007
Read_Master_Log_Pos: 194
Relay_Log_File: slave2-relay-bin-master1.000002
Relay_Log_Pos: 371
Relay_Master_Log_File: master1-bin.000007
Slave_IO_Running: Yes //正常
Slave_SQL_Running: Yes //正常
*************************** 2. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master2
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master2-bin.000001
Read_Master_Log_Pos: 1211
Relay_Log_File: slave2-relay-bin-master2.000002
Relay_Log_Pos: 420
Relay_Master_Log_File: master2-bin.000001
Slave_IO_Running: Yes //正常
Slave_SQL_Running: Yes //正常
测试
//master1 插入数据
mysql> insert into master1tab values (101010101010);
Query OK, 1 row affected (0.00 sec)
//master2插入数据
mysql> insert into master1tab values (151515151515);
Query OK, 1 row affected (0.00 sec)
//slave1查看
mysql> select * from master1tab;
+-----------------------------+
| name |
+-----------------------------+
| 1111 |
| 2222 |
| 33333333 |
| 44444 |
| 88888 |
| 80000 |
| 111111111111111 |
| 1988888 |
| 9999999 |
| 888888888888888 |
| 777777777777777777777777777 |
| 1010101010 |
| 90909090 |
| 101010101010 |
| 151515151515 |
+-----------------------------+
15 rows in set (0.00 sec) //slave1正常同步
//slave2查看
mysql> select * from master1tab;
+-----------------------------+
| name |
+-----------------------------+
| 1111 |
| 2222 |
| 33333333 |
| 44444 |
| 88888 |
| 80000 |
| 111111111111111 |
| 1988888 |
| 9999999 |
| 888888888888888 |
| 777777777777777777777777777 |
| 1010101010 |
| 90909090 |
| 101010101010 |
| 151515151515 |
+-----------------------------+
15 rows in set (0.00 sec) //slave2正常同步
Mysql错误代码解决
错误解决:
错误代码1593:
gtid或者uuid问题
错误代码1062:
SQl:NO
日志位置的问题
reset master;
错误代码2026:
在远程连接mysql时候可能会出现下面的问题:
ERROR 2026 (HY000): SSL connection error: protocol version mismatch
错误2026(hy000):SSL连接错误:协议版本不匹配
解决办法:在你要连接的个mysql的 /etc/my.cnf下添加一行:skip_ssl
错误代码1236:
解决方法:
1.在主库上执行以下命令,查询gtid_purged,记录下改值
mysql> show global variables like '%gtid%'\G
2.在从库上执行以下命令,查询已经执行过的gtid即gtid_executed,记录下主库的值,本机的不需要
show global variables like 'gtid'
;
3.在从库上执行以下命令停止同步线程及重置同步相关信息
mysql> stop slave;
mysql> reset slave;
mysql> reset master;
4.在从库上设置gtid_purged
该值有两个来源,一是在主库上查询的gtid_purged,二是在从库上查询的已经执行过的gtid_executed值(本机的就不需要,主库上gtid)
注意:一定记得加上从库上已经执行过的gtid,若只设置了主库上的gtid_purged,此时从库会重新拉取主库上所有的二进制日志文件,同步过程会出现其他错误,导致同步无法进行
mysql> set @@global.gtid_purged='主库gtid加上从库gtid';
注意:设置gtid_purged值时,gtid_executed值必须为空否则报错,该值清空的方法就是`reset master
命令执行完,再次查看相关信息
5.重新开启同步
mysql> change master to master_host='192.168.1.15',master_port=3306,master_user='repl',master_password='xxx',master_auto_position=1;
mysql> start slave;
当从库追赶上主库,此时测试主从数据是否一致,测试结果一切正常
mk-table-checksum h=192.168.1.15,u=root,p=xxx,P=3306 h=192.168.1.19,u=root,p=xxxx,P=3307 -d 6coursestudychoose_test | mk-checksum-filter
问题解决小技巧
reset slave
如下所示:
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> reset slave ;
Query OK, 0 rows affected (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
reset master
Deletes all binary log files listed in the index file, resets the binary log index file to be empty, and creates a new binary log file.
删除所有的二进制日志,并重新创建一个新的二进制日志
标签:affected,Mysql,Master,sec,mysql,master,root,集群 From: https://www.cnblogs.com/Jqazc/p/16848630.html