基础章节-01-MySQL数据库服务中级课程

图片

1.00 课程知识章节说明

目前在互联网的实际应用中,各个企业都会比较关注自身网站的数据信息,既要保证数据信息的安全性,同时也要保证数据存储读取效率 并且在特殊的场景下,还要对存储的数据信息进行检索和分析;因此数据库服务业务已经在各行各业应用非常的广泛 对于互联网领域的技术人员,对于数据库服务知识的掌握,也将是在求职时必备的技能,有些时候还会绝对入职的定级和薪资水平。

1.15 数据库服务冗余架构

1.15.1 数据库服务高可用前言介绍

数据库中的高可用功能,主要是用于避免数据库服务或数据信息的损坏问题,其中数据损坏的类型有: 数据物理损坏:磁盘、主机、程序实例、数据文件误删除 数据逻辑损坏:drop update … 其中,数据库高可用技术的出现主要解决的是数据逻辑损坏问题,而主从架构技术主要解决的是数据物理损坏问题; 数据库高可用解决方案选型依据:(全年无故障率)

无故障率故障时间解决方案
99.9%0.1%(525.6min)keepalived+双主架构,但需要人为干预
MHA ORCH TMHA,具有自动监控,自动切换,自动数据补偿,但还是属于半自动化
99.99%0.01%(52.56min)
比较适合非金融类互联网公司 eg: facebook taobao前端-TMHA–>polaradb
PXC MGR MGC,数据是高一致性
99.999%0.001%(5.256min)
比较适合金融类互联网公司
99.9999%0.0001%(0.5256min)自动化、云计算化、平台化,仍然属于概念阶段

1.15.2 数据库服务高可用软件介绍

MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton研发, 此人目前就职于Facebook公司,MHA是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。 MySQL进行故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换过程中; MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。 MHA主要有两部分组成: MHA Manager(管理节点) 可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave上。 MHA Node(数据节点) 运行在每台MySQL服务器上 MHA Manager 会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master; 然后将所有其他的slave重新指向新的master,整个故障转移过程对应用程序是完全透明的; MHA软件结构介绍:(MHA中的所有组件就是perl语言编写的功能脚本)

节点信息软件组件作用介绍
MHA Manager(管理节点)masterha_manger用于启动MHA
masterha_check_ssh用于检查MHA的SSH配置互信状况
masterha_check_repl用于检查MySQL复制状态,以及配置信息
masterha_master_monitor用于检测master是否宕机
masterha_check_status用于检测当前MHA运行状态
masterha_master_switch用于控制故障转移(自动或者手动)
masterha_conf_host添加或删除配置的server信息
MHA Node(数据节点)save_binar y_logs保存和复制master的二进制日志
apply_diff_relay_logs识别差异的中继日志事件并将其差异的事件应用于其他slave
purge_relay_logs清除中继日志(不会阻塞SQL线程)

1.15.3 数据库服务高可用环境构建

① MHA高可用架构基础环境: 为了实现MHA高可用架构构建,需要准备好三节点数据库+GTID复制环境:

主机角色主机名称地址信息
主库服务器192.168.30.1013306
从库服务器192.168.30.1023306
从库服务器192.168.30.103(兼做管理节点)3306

对原有数据库服务环境清理:(基于GTID环境构建)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 在所有主从节点均进行清理操作:
[root@xiaoQ-01 ~]# pkill mysqld
[root@xiaoQ-01 ~]# rm -rf /data/3306/*
[root@xiaoQ-01 ~]# rm -rf /data/binlog/*
[root@xiaoQ-01 ~]# mv /etc/my.cnf /tmp
[root@xiaoQ-01 ~]# mkdir -p /data/3306/data /data/binlog
[root@xiaoQ-01 ~]# chown -R mysql.mysql /data/*
-- 所有数据库主从节点均进行以上清理操作;
# 主库db01配置文件编写
cat >/etc/my.cnf <<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3306/data
socket=/tmp/mysql.sock
server_id=51
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db01 [\\d]>
EOF
# 从库db02配置文件编写
cat >/etc/my.cnf <<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3306/data
socket=/tmp/mysql.sock
server_id=52
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db02 [\\d]>
EOF
# 从库db03配置文件编写
cat >/etc/my.cnf <<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3306/data
socket=/tmp/mysql.sock
server_id=53
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db03 [\\d]>
EOF
# 进行数据库所有节点初始化操作
[root@xiaoQ-01 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3306/data
[root@xiaoQ-02 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3306/data
[root@xiaoQ-03 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3306/data
# 启动数据库所有节点服务
[root@xiaoQ-01 ~]# /etc/init.d/mysqld start
[root@xiaoQ-02 ~]# /etc/init.d/mysqld start
[root@xiaoQ-03 ~]# /etc/init.d/mysqld start
# 重构主从关系-主库操作
db01 [(none)]>create user repl@'192.168.30.%' identified with mysql_native_password by '123456';
Quer y OK, 0 rows affected (0.01 sec)
db01 [(none)]>grant replication slave on *.* to repl@'192.168.30.%';
Quer y OK, 0 rows affected (0.00 sec)
-- 主库上创建主从复制用户信息
# 重构主从关系-从库操作
db02 [(none)]>change master to
master_host='192.168.30.101',
master_user='repl',
master_password='123456',
master_auto_position=1;
-- 表示让从库自己找寻复制同步数据的起点;
-- 在第一次启动gtid功能时,会读取从库中的binlog日志信息,根据主库uuid信息,获取从库中执行过的主库gtid信息
-- 从从库中没有执行过的主库gtid信息之后进行进行数据同步操作
db02 [(none)]> start slave;
-- 其他从库一并操作

② MHA高可用软件安装部署:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# 创建程序命令软链接
[root@xiaoQ-01 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog/usr/bin/mysqlbinlog
[root@xiaoQ-01 ~]# ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql
-- 所有节点均执行以上操作,因为MHA程序加载数据库命令,会默认在/usr/bin下面进行加载(会影响数据补偿和监控功能)
# 配置各节点互信
[root@xiaoQ-01 ~]# rm -rf /root/.ssh
[root@xiaoQ-01 ~]# ssh-keygen
[root@xiaoQ-01 ~]# cd /root/.ssh
[root@xiaoQ-01 ~]# mv id_rsa.pub authorized_keys
[root@xiaoQ-01 ~]# scp  -r  /root/.ssh  192.168.30.102:/root
[root@xiaoQ-01 ~]# scp  -r  /root/.ssh  192.168.30.103:/root
ssh 192.168.30.101 date
ssh 192.168.30.102 date
ssh 192.168.30.103 date
-- 各节点验证
# 安装软件程序
yum install perl-DBD-MySQL -y
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
-- 所有节点安装Node软件依赖包
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
yum install -y mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
-- Manager软件安装(db03)
# 在db01主库中创建mha需要的用户
create user mha@'192.168.30.%' identified with mysql_native_password by 'mha';
grant all privileges on *.* to mha@'192.168.30.%';
-- 在主库创建完毕后,主从复制功能,核实所有从库也都有mha用户信息
# Manager配置文件准备(db03)
mkdir -p /etc/mha
-- 创建配置文件目录
mkdir -p /var/log /mha/app1
-- 创建日志目录
cat > /etc/mha/app1.cnf <<EOF
[server default]
manager_log=/var/log /mha/app1/manager
-- MHA的工作日志设置
manager_workdir=/var/log /mha/app1
-- MHA的工作目录
master_binlog_dir=/data/binlog
-- 主库的binlog目录
user=mha
-- 监控用户,利用此用户连接各个节点,做心跳检测(主要是检测主库的状态)
password=mha
-- 监控密码
ping_interval=2
-- 心跳检测的间隔时间
repl_password=123456
-- 复制密码
repl_user=repl
-- 复制用户(用于告知从节点通过新主同步数据信息的用户信息)
ssh_user=root
-- ssh互信的用户(可以利用互信用户从主库scp获取binlog日志信息,便于从库进行数据信息补偿)
[server1]
-- 节点信息....
hostname=192.168.30.101
port=3306
[server2]
hostname=192.168.30.102
port=3306
candidate_master=1
[server3]
hostname=192.168.30.103
port=3306
EOF
-- 编辑mha配置文件
# MHA状态检查(db03)
masterha_check_ssh   --conf=/etc/mha/app1.cnf
Wed Dec 28 20:54:42 2022 - [info] All SSH connection tests passed successfully.
-- 在MHA管理节点,进行ssh互信功能检查,并且显示成功表示检查通过
masterha_check_repl  --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.
-- 在MHA管理节点,检查主从关系与配置文件信息是否正确
# 开启MHA-manager
开启MHA(db03)nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null> /var/log /mha/app1/manager.log 2>&1 &
# 查看MHA状态
[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:30770) is running(0:PING_OK), master :192.168.30.101
-- 显示以上提示信息,表示MHA基础环境搭建成功了,但还不能在生产环境使用,还需要有后续的操作配置

1.15.4 数据库服务高可用工作原理

在熟悉高可用服务工作原理前,可以先思考下应用高可用服务可以解决哪些需求,或者也可以理解为解决哪些痛点: ① 如何在高可用架构中,当主库宕机异常后,使之及时的发现主库服务程序产生了运行异常? 解决此痛点问题,需要实现高可用的监控需求; ② 如何在高可用架构中,当主库宕机异常后,可以找到可以替代主库的服务器主机进行切换? 解决此痛点问题,需要实现高可用的选主功能;(并且选择数据量越接近主库的从库成为新主) ③ 如何在高可用架构中,当主库宕机异常后,新的主库接管后可以保证与原有主库数据一致? 解决此痛点问题,需要实现高可用的数据补偿; ④ 如何在高可用架构中,当主库宕机异常后,将应用程序的读写请求对接切换到新的主库上? 解决此痛点问题,需要实现高可用的应用透明;(VIP技术) ⑤ 如何在高可用架构中,当主库宕机异常后,能够及时向管理员发起告知提醒使之进行修复?(MHA切换是一次性的) 解决此痛点问题,需要实现高可用的报警功能; ⑥ 如何在高可用架构中,当主库宕机异常后,当整体主库系统环境都异常时实现数据的补偿? 解决此痛点问题,需要实现高可用的额外补偿; ⑦ 如何在高可用架构中,当主库宕机异常后,根据主库服务器的异常情况进行原有主库修复? 解决此痛点问题,需要实现高可用的自愈功能;(待开发,只有云平台RDS具有此功能)

图片

MHA的设计原理分析(Failover 过程) 01 MHA软件启动 根据启动命令,分析MHA软件启动原理:

1
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null> /var/log /mha/app1/manager.log 2>&1 &

根据以上启动命令,需要先调取MHA启动脚本文件masterha_manager ,然后在调取加载MHA软件的配置文件–conf=…/app1.cnf 会根据加载的MHA的配置文件不同,实现管理多个高可用架构环境,进行高可用业务的架构环境的区分; –remove_dead_master_conf 参数表示在主节点出现宕机情况时,将会从集群中被踢出,即从配置文件中删除掉故障节点; –ignore_last_failover 默认MHA服务是不能频繁进行故障切换的,需要有一定的间隔时间,加此参数表示忽略切换的间隔时间; 最后将MHA启动运行的信息放入到日志文件中即可 /var/log/mha/app1/manager.log 2>&1 02 MHA实现监控 利用MHA启动脚本文件masterha_manager 会自动调用监控脚本文件masterha_master_monitor ,并且每隔配置文件指定时间; ping_interval=2 进行脚本监控一次,从而判断主节点是否处于存活状态,连续4次还没有主库心跳,即说明主库宕机;

1
2
3
4
5
6
7
8
# 监控脚本验证主节点存活方法
[root@xiaoQ-03 ~]# mysql -umha -pmha -h192.168.30.101 -e "select user();"
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------------+
| user()                 |
+-------------------+
| mha@xiaoQ-03 |
+-------------------+

03 MHA选主过程 在MHA中进行选主时,根据选主源码文件信息分析,主要会利用到四个数组:alive latest pref bad,并且会识别节点编号信息; 在进行选主时,主要会关注竞选新主节点的日志量、以及是否设置candidate_master参数配置信息;

数组信息简述作用说明
alive存活数组主要用于探测存活的节点状态;当主库宕机后,探测的就是两个从库节点
latest最新数组表示获取日志最新的从库信息,即数据量最接近主库的从库(根据GTID信息 或 position信息)
pref备选数组在数组中具有candidate_master参数判断条件,此参数可以放入配置文件节点中,便于节点优先选择为新主
如果设定了参数:no_master=1,表示相应节点不参与竞选主;
bad不选数组如果设定了参数:log_bin=0(二进制日志没开),表示相应节点不参与竞选主;
如何设定了参数:check_slave_delay,检查从库延迟主库100M数据信息日志量,表示节点不参与竞选主

MHA选主判断总结(利用if判断选主的情况) 循环对比latest数组和pref数组的slave,如果存在相同的slave,并且这个slave不在bad数组当中,该slave会被推选为新的master DB02节点即满足latest数组信息,又满足perf数组信息,但不满足bad数据信息,即会被选为新主,有多个按照号码顺序选举; 如果pref和bad数组当中的个数为0,则选择latest数组当中的第一个slave为master; DB02节点没有candidate_master参数配置,又没有不选数组里的三种情况配置,即db02恰好是latest,为新主; 循环对比alive数组和pref数组当中的slaves,如果有一个slave相同,并且不在bad数组当中,该节点就会成为新的master; DB02节点即不满足latest,也不满足bad,但是满足pref,也会被选择作为新主; 循环latest数组,如果又循环到slave不在bad数组当中,这个slave就会成为master,就算添加了candidate_master=1参数; 该slave也不一定会成为主库; DB02节点即满足latest数组,不是bad数组,也会成为新的主; 从活着的slave当中进行循环,如果循环到slave不在bad数组当中,那么这个slave就会成为主库; DB02节点是活着的,不满足bad,也可以成为新的主; 如果进行了多次选择都找不到主库,那么主库选择失败,failover失败; 选主策略简述表:

优先级alive数组latest数组pref数组bad数组选主策略多个选择情况
01满足满足满足不满足优选选择按照节点号码顺序选择
02满足满足不满足不满足优选选择按照节点号码顺序选择
满足满足
03不满足不满足优选选择按照节点号码顺序选择
04满足不满足不满足不满足优选活着节点按照节点号码顺序选择

说明:在进行手工指定切换新主时,即应用了prio_new_master_host参数信息时,会最优先选择相应节点为新主; 04 MHA数据补偿 在进行数据补偿之前,需要让新主库与原有宕机主库进行对比,获悉需要补偿的数据量情况,即对比差的数据日志量信息; 然后可以从binlog日志中,进行补充数据信息的截取,随之进行数据信息补偿,但是有种特殊情况,若原有主库无法访问了; 所以进行数据补偿操作,也需要分各种情景进行处理: 原主库SSH连接正常: 各个从节点自动调用:save_binar y_logs 脚本文件,立即保存缺失部分的bin_log,到各节点/var/tmp/目录; 原主库SSH连接异常: 各个从节点自动调用:apply_diff_relay_logs 脚本文件,进行relay_log日志差异信息补偿; 额外特殊数据补充:(利用主库日志冗余机制) MHA提供了binlog_server功能,可以实时拉取主库的binlog日志到备份节点,从而进行数据额外补偿; 05 MHA业务切换 自动解除原有的主从关系,实现新的主从关系的建立;

1
2
3
4
5
# 所有从库解除主从关系操作
stop slave;
reset slave;
# 所有从库重构主从关系操作
change master to ...

06 MHA应用透明 实现MHA的VIP功能,利用脚本实现,上传mha_script.tar文件到/usr/local/bin目录中,然后进行解压处理;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 上传MHA所需的脚本文件
[root@xiaoQ-03 ~]# cd /usr/local/bin/
[root@xiaoQ-03 bin]# chmod +x /usr/local/bin/*
# 修改MHA脚本文件的信息
[root@xiaoQ-03 bin]# cp master_ip_failover master_ip_failover.bak
[root@xiaoQ-03 bin]# dos2unix /usr/local/bin/*
[root@xiaoQ-03 bin]# vim master_ip_failover
13 my $vip = '192.168.30.110/24';
14 my $key = '1';
15 my $if = 'eth0';
16 my $ssh_start_vip = "/sbin/ifconfig $if:$key $vip";
17 my $ssh_stop_vip = "/sbin/ifconfig $if:$key down";
18 my $ssh_Bcast_arp= "/sbin/arping -I $if -c 3 -A 192.168.30.110";
# 修改配置文件
[root@xiaoQ-03 ~]# vim /etc/mha/app1.cnf
master_ip_failover_script=/usr/local/bin/master_ip_failover
# 重启MHA服务
[root@xiaoQ-03 bin]# masterha_stop --conf=/etc/mha/app1.cnf
[root@xiaoQ-03 bin]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null>
/var/log /mha/app1/manager.log 2>&1 &
# 手工在主库上添加VIP
[root@xiaoQ-03 bin]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:103046) is running(0:PING_OK), master :192.168.30.101
-- 核实此时的MHA的主库节点
ifconfig eth0:1 192.168.30.110/24
-- 在主库节点手工添加vip地址信息
# 进行VIP地址连接测试
-- 可以使用navcat软件,连接MHA的vip地址,查看所连主机信息是否为主节点,当故障转移后可以核实VIP地址是否持续连接;

说明:进行MHA的VIP地址漂移时,只能在局域网环境进行漂移,不能实现跨网段的VIP地址漂移; 07 MHA故障报警 实现MHA的报警功能,利用脚本实现,上传mha_script.tar文件到/usr/local/bin目录中,然后进行解压处理;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 准备脚本文件
[root@xiaoQ-03 bin]# cp send_report send_report.bak
28 my $smtp='smtp.qq.com';
-- smtp服务器地址域名
29 my $mail_from='330882721@qq.com';
-- 发件箱信息配置
30 my $mail_user='330882721';
-- 用户名 QQ号
31 my $mail_pass='ypokkranqlgkcbba';
-- 邮箱授权码
32 my $mail_to='330882721@qq.com';
or
my $mail_to=['to1@qq.com','to2@qq.com'];
-- 收件箱信息配置
# 修改配置文件
[root@xiaoQ-03 ~]# vim /etc/mha/app1.cnf
report_script=/usr/local/bin/send_report
# 重启MHA服务
[root@xiaoQ-03 bin]# masterha_stop --conf=/etc/mha/app1.cnf
[root@xiaoQ-03 bin]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null>
/var/log /mha/app1/manager.log 2>&1 &

08 MHA额外补偿 利用binlog_server作为额外的日志补偿的冗余方案,即实时保存主库的bin_log日志文件到特定节点目录中;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建日志存放目录
[root@xiaoQ-03 ~]# mkdir -p /data/binlog_server/
[root@xiaoQ-03 ~]# chown -R mysql.mysql /data/*
[root@xiaoQ-03 ~]# cd /data/binlog_server
[root@xiaoQ-03 binlog_server]# mysql -e "show slave status\G"|grep "Master_Log"
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 1201
Relay_Master_Log_File: mysql-bin.000002
Exec_Master_Log_Pos: 1201
-- 拉取日志的起点,需要按照目前从库的已经获取到的二进制日志点为起点
[root@xiaoQ-03 binlog_server]# mysqlbinlog -R --host=192.168.30.101 --user=mha --password=mha --raw --stop-never mysql-bin.000002 &
# 编写配置文件信息
[root@xiaoQ-03 ~]# vim /etc/mha/app1.cnf
[binlog1]
no_master=1
hostname=192.168.30.103
master_binlog_dir=/data/binlog_server/
# 重启MHA服务
[root@xiaoQ-03 bin]# masterha_stop --conf=/etc/mha/app1.cnf
[root@xiaoQ-03 bin]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null>
/var/log /mha/app1/manager.log 2>&1 &

1.15.5 数据库服务高可用故障切换

模拟进行指定主库节点故障情况,检查核实MHA相应功能脚本是否能够正确运行:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 确认目前的MHA的状态是良好的
[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:30770) is running(0:PING_OK), master :192.168.30.101
# 模拟DB01数据库节点宕机
[root@xiaoQ-01 ~]# /etc/init.d/mysqld stop
Shutting down MySQL........... SUCCESS!
# 监控DB03日志信息的变化
[root@xiaoQ-03 ~]# tail -f /var/log /mha/app1/manager
Mon Jan  2 15:32:26 2023 - [warning] Got error on MySQL select ping: 1053 (Server shutdown in progress)
Mon Jan  2 15:32:26 2023 - [info] Executing SSH check script: exit 0
Mon Jan  2 15:32:26 2023 - [info] HealthCheck: SSH to 192.168.30.101 is reachable.
Mon Jan  2 15:32:28 2023 - [warning] Got error on MySQL connect: 2003 (Can't connect to MySQL server on '192.168.30.101' (111))
... 省略部分信息...

实现MHA高可用切换的六个步骤: 01 MHA健康检查报错,显示主数据库节点无法正常连接

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 日志信息分析
[waring] Got error on MySQL connect: 2003 (Can't connect to MySQL server on '192.168.30.101' (111))
[waring] Connection failed 2 time(s)..
[waring] Got error on MySQL connect: 2003 (Can't connect to MySQL server on '192.168.30.101' (111))
[waring] Connection failed 3 time(s)..
[waring] Got error on MySQL connect: 2003 (Can't connect to MySQL server on '192.168.30.101' (111))
[waring] Connection failed 4 time(s)..
[waring] Master is not reachable from health checker!
[waring] Master 192.168.30.101(192.168.30.101:3306) is not reachable!
-- 对故障主节点进行4次健康检查,主节点数据库服务仍旧无法连接,即判定主节点故障

02 MHA进行重新选主,根据数组信息选择合适的备用新主节点

1
2
3
4
5
6
7
[info] Connecting to a master server failed. Reading configuration file /etc/masterha_default.cnf and /etc/mha/app1.cnf again, and tr ying to connect to all servers
to check server status..
[info] Reading application default configuration from /etc/mha/app1.cnf
....
[info] Starting master failover
....
[info] ** Phase 1: Configuration Check Phase completed.

03 MHA进行节点关闭,选择完新的主节点后会将原有主节点的VIP地址消除

1
2
3
[info] * Phase 2: Dead Master Shutdown Phase..
[info] Forcing shutdown so that applications never connect to the current master..
Disabling the VIP on old master : 192.168.30.101

04 MHA进行节点切换,在新的主节点上进行非同步数据信息的补偿,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[info] * Phase 3: Master Recovery Phase..
[info] * Phase 3.1: Getting Latest Slaves Phase..
....
[info] * Phase 3.3: Determining New Master Phase..
[info] New master is 192.168.30.102(192.168.30.102:3306)
[info] Starting master failover..
[info] * Phase 3.3: New Master Recovery Phase..
[info] Executing binlog save command: save_binar y_logs --command=save --start_file=mysql-bin.000002  --start_pos=1201 --
output_file=/var/tmp/saved_binlog_binlog1_20230102153233.binlog --handle_raw_binlog=0 --skip_filter=1 --disable_log_bin=0 --manager_version=0.58 --
oldest_version=8.0.26  --binlog_dir=/data/binlog_server/
[info] Additional events were not found from the binlog server. No need to save.
Enabling the VIP - 192.168.30.110/24 on the new master - 192.168.30.102
Mon Jan  2 15:32:36 2023 - [info]  OK.
Mon Jan  2 15:32:36 2023 - [info] ** Finished master recovery successfully.
[info] * Phase 3: Master Recovery Phase completed.

05 MHA进行主从重构,将从库连接到新的主库上

1
2
3
4
5
6
[info] * Phase 4: Slaves Recovery Phase..
[info] * Phase 4.1: Starting Slaves in parallel..
[info]  Resetting slave 192.168.30.103(192.168.30.103:3306) and starting replication from the new master 192.168.30.102(192.168.30.102:3306)..
[info]  Executed CHANGE MASTER.
[info]  Slave started.
[info]  All new slave servers recovered successfully.

06 MHA切换完毕过程,架构故障转移切换完毕后做清理阶段,并进行最终汇报

1
2
3
4
[info] * Phase 5: New master cleanup phase..
----- Failover Report -----
Master failover to 192.168.30.102(192.168.30.102:3306) completed successfully.
Mon Jan  2 15:32:37 2023 - [info] Sending mail..

实现MHA高可用切换的最终结果: 01 MHA故障节点转移后,邮件信息提示:

图片

图片

02 核实MHA的VIP地址已经发生漂移: 03 核实MHA进行切换的新主从关系,以及配置文件中的故障节点信息已经踢除:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 获取新主从关系
[root@xiaoQ-03 ~]# mysql -e "show slave status\G"
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 192.168.30.102
Master_User : repl
Master_Port: 3306
# 查看MHA配置文件信息
[root@xiaoQ-03 ~]# cat /etc/mha/app1.cnf
[binlog1]
hostname=192.168.30.103
master_binlog_dir=/data/binlog_server/
no_master=1
[server default]
manager_log=/var/log /mha/app1/manager
manager_workdir=/var/log /mha/app1
master_binlog_dir=/data/binlog
master_ip_failover_script=/usr/local/bin/master_ip_failover
password=mha
ping_interval=2
repl_password=123456
repl_user=repl
report_script=/usr/local/bin/send_report
ssh_user=root
user=mha
[server2]
hostname=192.168.30.102
port=3306
[server3]
hostname=192.168.30.103
port=3306
-- 故障节点信息已从配置文件中清理

04 MHA程序终止(管理程序manager终止) 以上故障模拟操作完成后,查看MHA程序进程已经终止:

1
2
3
4
[root@xiaoQ-03 binlog_server]# ps -ef|grep mha
root     109328   1798  0 15:48 pts/0    00:00:00 grep --color=auto mha
[root@xiaoQ-03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 is stopped(2:NOT_RUNNING).

1.15.6 数据库服务高可用修复方法

MHA故障通用修复方法步骤:(前提是MHA进行正常故障切换,通过日志可以检查是否进行正常的故障转移) 01 检查节点状态:

1
2
3
4
5
6
7
# 检查节点数据库运行状态
[root@xiaoQ-01 ~]# /etc/init.d/mysqld status
ERROR! MySQL is not running
-- 发现数据库服务有异常节点进行恢复
[root@xiaoQ-01 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
-- 恢复DB01异常数据库服务节点

在实际生产环境中,如果主库异常无法实现重新启动修复,可能就需要准备一台新的节点主机,重新构建1主2从的架构; 但是如果使用新的节点主机,进行主从架构重构,修复高可用环境,就需要考虑新主机的在恢复数据的时间损耗; 总之,需要将新节点的数据信息进行同步后,再将新节点变为新的从库,从而修复高可用主从关系,具体如何修复数据需要考虑实际情况 02 检查主从关系:

1
2
3
4
5
6
7
8
[root@xiaoQ-03 ~]# mysql -e "show slave status\G"|grep "Master_Host"
Master_Host: 192.168.30.102
-- 确认切换后的新主库信息
[root@xiaoQ-02 ~]# /etc/init.d/mysqld status
SUCCESS! MySQL running (27332)
-- 在DB02上核实节点运行的状态
[root@xiaoQ-01 ~]# mysql -e "show slave status\G"|grep "Master_Host"
-- 在DB01上无法获取主从关系信息,需要修复DB01主从,最终实现1主2从效果

03 修复主从关系:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# DB01上修复主从
[root@xiaoQ-01 ~]# mysql
db02 [(none)]>change master to
master_host='192.168.30.102',
master_user='repl',
master_password='123456',
master_auto_position=1;
db02 [(none)]> start slave;
# DB01上核实主从关系
[root@xiaoQ-01 ~]# mysql -e "show slave status\G"|grep "Master_Host"
Master_Host: 192.168.30.102

04 检查虚拟地址:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[root@xiaoQ-02 ~]# ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:61:cd:06 brd ff:ff:ff:ff:ff:ff
inet 192.168.30.102/24 brd 192.168.30.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 192.168.30.110/24 brd 192.168.30.255 scope global secondar y eth0:1
valid_lft forever preferred_lft forever
inet6 fe80::560c:13cd:6107:b0de/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::727b:5d03:94c0:9382/64 scope link noprefixroute
valid_lft forever preferred_lft forever
ifconfig eth0:1 192.168.30.110/24
-- 如果上面vip漂移失败,出现问题可以手工添加VIP

05 恢复日志同步:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 检查binlog_server状态
[root@xiaoQ-03 ~]# ps -ef|grep mysqlbinlog
-- binlog_server日志同步进程消失
# 修复binlog_server状态
[root@xiaoQ-03 ~]# rm -rf /data/binlog_server/*
[root@xiaoQ-03 ~]# cd /data/binlog_server/
[root@xiaoQ-03 binlog_server]# mysql -e "show slave status\G"|grep "Master_Log"
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 1229
Relay_Master_Log_File: mysql-bin.000002
Exec_Master_Log_Pos: 1229
[root@xiaoQ-03 binlog_server]# mysqlbinlog -R --host=192.168.30.102 --user=mha --password=mha --raw --stop-never mysql-bin.000002 &
[root@xiaoQ-03 binlog_server]# ll
总用量 4
-rw-r----- 1 root root 1229 1月   2 16:28 mysql-bin.000002

06 调整配置文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 确认核实配置文件中三个节点信息
[root@xiaoQ-03 binlog_server]# cat /etc/mha/app1.cnf
[binlog1]
hostname=192.168.30.103
master_binlog_dir=/data/binlog_server/
no_master=1
[server default]
manager_log=/var/log /mha/app1/manager
manager_workdir=/var/log /mha/app1
master_binlog_dir=/data/binlog
master_ip_failover_script=/usr/local/bin/master_ip_failover
password=mha
ping_interval=2
repl_password=123456
repl_user=repl
report_script=/usr/local/bin/send_report
ssh_user=root
user=mha
[server2]
hostname=192.168.30.102
port=3306
[server3]
hostname=192.168.30.103
port=3306
[server1]
hostname=192.168.30.101
port=3306
-- 添加DB01故障节点到配置文件中
[root@xiaoQ-03 ~]# masterha_conf_host --command=add --conf=/etc/mha/app1.cnf --hostname=192.168.30.101 --block=server1 --params="port=3306"
-- 利用命令脚本添加新的节点信息
[root@xiaoQ-03 ~]# masterha_conf_host --command=delete --conf=/etc/mha/app1.cnf --block=server1
-- 利用命令脚本删除指定的节点信息

07 核实互信情况:

1
2
3
4
[root@xiaoQ-03 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
Mon Jan  2 16:42:35 2023 - [info] All SSH connection tests passed successfully.
[root@xiaoQ-03 binlog_server]# masterha_check_repl --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.

08 恢复启动MHA:

1
2
3
4
[root@xiaoQ-03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null>
/var/log /mha/app1/manager.log 2>&1 &
[root@xiaoQ-03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:109463) is running(0:PING_OK), master :192.168.30.102

1.15.7 数据库服务高可用维护操作

实现MHA高可用主节点在线切换(手工操作) 可以在主库没有故障的情况下,利用手工方式将主库业务切换到其它的从库节点上,从而解放原有主库节点(维护性操作时应用);

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 关闭MHA服务程序
masterha_stop --conf=/etc/mha/app1.cnf
-- 关闭mha程序是保证手工切换时,不会受到mha自动切换的影响
# 执行MHA手工切换
masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=alive --new_master_host=192.168.30.101 --orig_master_is_new_slave --
running_updates_limit=10000
...省略部分信息...
It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before switching. Is it ok to execute on 192.168.30.102(192.168.30.102:3306)? (YES/no):
-- 以上说明信息,表示在进行切换之前,在原有主库节点执行FLUSH NO_WRITE_TO_BINLOG TABLES这个命令
-- 此命令表示,关闭所有打开的表,强制关闭所有正在使用的表,不写入binlog;
-- 因为此时VIP还没有漂移,表示禁止原主库继续写入数据信息
# 关闭原主库的写入功能
db02 [(none)]>FLUSH NO_WRITE_TO_BINLOG TABLES;
Quer y OK, 0 rows affected (0.01 sec)
It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before switching. Is it ok to execute on 192.168.30.102(192.168.30.102:3306)? (YES/no):
yes
Starting master switch from 192.168.30.102(192.168.30.102:3306) to 192.168.30.101(192.168.30.101:3306)? (yes/NO): yes
-- 进行再一次核实确认,是否进行手工切换
master_ip_online_change_script is not defined. If you do not disable writes on the current master manually, applications keep writing on the current master. Is it
ok to proceed? (yes/NO): yes
-- 表示master_ip_online_change_script此脚本没有定义,如果没有禁止当前主库写入的禁止,业务应用仍旧访问当前主库
-- 因为此时VIP还没有进行转移;
[info] Switching master to 192.168.30.101(192.168.30.101:3306) completed successfully.
-- 提示切换完成
# 进行MHA切换核验
[root@xiaoQ-03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null>
/var/log /mha/app1/manager.log 2>&1 &
-- 重新启动MHA程序
[root@xiaoQ-03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
[1]+  退出 1                nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null >
/var/log /mha/app1/manager.log 2>&1
-- 检查状态失败,mha没有启动成功,因为vip信息并没有进行有效漂移
masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=alive --new_master_host=192.168.30.102 --orig_master_is_new_slave --
running_updates_limit=10000
-- 临时先切换回原有主节点,恢复MHA服务状态
[root@xiaoQ-03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null>
/var/log /mha/app1/manager.log 2>&1 &
[1] 65799
[root@xiaoQ-03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:65799) is running(0:PING_OK), master :192.168.30.102
-- mha服务状态恢复

执行切换命令参数信息说明:

序号参数信息解释说明
01–master_state执行手工切换的状态,alive表示主节点存活状态进行切换
02–new_master_host指定切换后的新主库节点的地址信息
03–orig_master_is_new_slave将原有主库指定为新的从库角色
04–running_updates_limit指定切换过程的时间限制,超过指定时间未完成切换,即切换失败,单位毫秒

在进行MHA高可用节点在线手工切换时,有以下信息需要注意: 在进行MHA高可用手工切换时,无法自动调整原有主库的binlog_server,需要手工重新拉取新主库的binlog; 在进行MHA高可用手工切换时,无法进行触发邮件脚本功能,邮件发送功能只能在MHA产生故障转移时触发; 在进行MHA高可用手工切换时,需要进行架构主从关系的切换,以及可以调整转移VIP地址信息; 在进行MHA高可用手工切换时,需要对切换前的主库进行锁定(FTWRL flush tables with read lock),避免数据不一致 进行MHA手工在线切换的合理操作: 01 应用master_ip_online_change_script功能脚本 功能描述:此脚本可以在线进行切换时,自动锁定原主库,以及将原主库VIP地址进行自动飘移; 编写应用切换脚本文件信息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 编写MHA手工切换脚本文件
[root@xiaoQ-03 ~]# cd /usr/local/bin/
[root@xiaoQ-03 bin]# cp master_ip_online_change master_ip_online_change.bak
[root@xiaoQ-03 bin]# vim master_ip_online_change
21 my $vip = "192.168.30.110";
22 my $key = "1";
23 my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
24 my $ssh_stop_vip = "/sbin/ifconfig eth0:$key $vip down";
25 my $ssh_Bcast_arp= "/sbin/arping -I eth0 -c 3 -A 192.168.30.110";
# 修改MHA服务程序配置文件
[root@xiaoQ-03 ~]# vim /etc/mha/app1.cnf
master_ip_online_change_script=/usr/local/bin/master_ip_online_change
# 关闭MHA服务程序进行核查
[root@xiaoQ-03 ~]# masterha_stop --conf=/etc/mha/app1.cnf
[root@xiaoQ-03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
[root@xiaoQ-03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.
# 进行MHA服务手工在线切换
[root@xiaoQ-03 ~]# masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=alive --new_master_host=192.168.30.101 --orig_master_is_new_slave --
running_updates_limit=10000
...省略部分信息...
It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before switching. Is it ok to execute on 192.168.30.102(192.168.30.102:3306)? (YES/no):
yes
-- FLUSH NO_WRITE_TO_BINLOG TABLES 命令在原有主库节点需要再执行一次;
Starting master switch from 192.168.30.102(192.168.30.102:3306) to 192.168.30.101(192.168.30.101:3306)? (yes/NO): yes
Sat Jan  7 13:48:50 2023 - [info] Switching master to 192.168.30.101(192.168.30.101:3306) completed successfully.
# 重构binlogserver功能
[root@xiaoQ-03 ~]# cd /data/binlog_server/
[root@xiaoQ-03 binlog_server]# rm -rf ./*
[root@xiaoQ-03 binlog_server]# mysql -e "show slave status\G"|grep "Master_Log"
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 236
Relay_Master_Log_File: mysql-bin.000005
Exec_Master_Log_Pos: 236
[root@xiaoQ-03 binlog_server]# mysqlbinlog -R --host=192.168.30.101 --user=mha --password=mha --raw --stop-never mysql-bin.000005 &
-- 此功能不进行重新配置,会导致MHA服务无法正常启动(若已经启动过,可以将进程杀死,重新启动)
# 进行MHA服务手工切换核验:
[root@xiaoQ-03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null>
/var/log /mha/app1/manager.log 2>&1 &
-- 重新启动MHA程序
[root@xiaoQ-03 binlog_server]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:17462) is running(0:PING_OK), master :192.168.30.101

1.16 数据库服务读写分离

1.16.1 数据库服务读写分离概述介绍

在应用数据库主从架构或者数据库冗余架构时,都可以有效保证数据库逻辑故障或物理故障对业务的影响; 但是,这两种架构进行应用时,业务访问过程只是访问主数据库节点,进行读写操作,当并发量大时无型中会对主节点造成不小压力; 因此,可以设计一种新型的业务访问架构方式,可以实现将写数据请求发送到主节点,将读数据请求发送到从节点; 最终,可以有效减少主节点的业务访问压力,这样设计的数据库架构称之为读写分离架构;

1.16.2 数据库服务读写分析原理分析

读写分离架构最终目的:实现业务写的请求到达主库,实现业务读的请求到达从库,从而减少主库的压力,实现不同请求的压力分担; 可以利用读写分离中间件实现以上的功能需求:atlas(360公司出品) proxySQL 利用读写分离中间件的设置,当业务请求有select查询时,将请求发送给从库,当业务请求有update insert等修改时,将请求发送给主库

图片

proxySQL是基于MySQL的一款开源的中间件的产品,是一个灵活的MySQL代理层,可以实现读写分离: proxySQL数据库中间件支持Quer y路由功能; pxoxySQL数据库中间件支持动态指定某个SQL进行缓存; proxySQL数据库中间件支持动态加载配置信息(无需重启ProxySQL服务) proxySQL数据库中间件支持故障切换和SQL的过滤功能 ProxySQL的参考网站连接: https://www.proxysql.com/ https://github.com/sysown/proxysql/releases

1.16.3 数据库服务读写分离架构搭建

步骤一:读写分离架构部署环境规划 为了实现读写分离架构构建,需要准备好三节点数据库+GTID复制环境+MHA环境(普通主从环境也可以构建);

主机角色主机名称地址信息
主库服务器192.168.30.1013306
从库服务器192.168.30.1023306
从库服务器192.168.30.103(兼做管理节点)3306

步骤二:读写分离架构软件下载安装 通过官方网站或者github可以下载proxySQL软件程序,并上传到数据库服务器中进行安装;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 上传安装软件程序
[root@xiaoQ-03 ~]# rpm -ivh proxysql-2.4.6-1-centos7.x86_64.rpm
警告:proxysql-2.4.6-1-centos7.x86_64.rpm: V4 RSA/SHA512 Signature, 密钥 ID 8217c97e: NOKEY
准备中...                          ################################# [100%]
# 启动运行软件程序
[root@xiaoQ-03 ~]# systemctl start proxysql
[root@xiaoQ-03 ~]# netstat -lntup
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0            0         0.0.0.0:6032                  0.0.0.0:*               LISTEN      83020/proxysql
tcp        0            0         0.0.0.0:6033                  0.0.0.0:*               LISTEN      83020/proxysql
-- 启动生成的6032端口为管理端口,用于配置数据库中间件的功能信息连接此端口
-- 启动生成的6033端口为访问端口,用于提供对外的业务访问此端口

步骤三:读写分离架构软件管理配置 在连接进入6032端口之后,表示进行proxysql的管理终端环境,终端环境中会加载五个重要的功能库:

序号库信息配置信息解释说明
main
01mysql_servers表示后端可以连接mysql服务器的列表
mysql_users表示配置后端数据库的连接账号和监控账号
mysql_query_rules表示指定query路由到后端不同服务器的规则列表
mysql_replication_hostgroups表示节点分组配置信息,可以配置多个写或读节点到一个组中
02disk表示持久化的磁盘配置信息
03stats表示统计信息的汇总
monitor
04表示监控收集的信息,比如数据库的监控状态等
05stats_history表示收集的有关软件内部功能的历史指标

说明:一般服务是通过配置文件保存功能配置信息,proxySQL是通过数据库中的表进行配置信息的存储设置;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 连接进入到proxySQL管理终端
[root@xiaoQ-03 ~]# mysql -uadmin -padmin -h127.0.0.1 -P6032
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 1
Server version: 5.5.30 (ProxySQL Admin Module)
# 查看proxySQL终端数据库信息
>show databases;
+-----+-----------------+----------------------------------------------+
| seq | name              | file                                                         |
+-----+-----------------+----------------------------------------------+
| 0     | main               |                                                               |
| 2     | disk                | /var/lib/proxysql/proxysql.db            |
| 3     | stats               |                                                               |
| 4     | monitor          |                                                               |
| 5     | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+-----------------+----------------------------------------------+
5 rows in set (0.00 sec)
-- 不需要use到相应数据库中进行操作,可以操作的数据表信息如下
# 查看proxySQL终端数据表信息
>show tables ;
+-----------------------------------------------------------------+
| tables
+-----------------------------------------------------------------+
| global_variables
| mysql_aws_aurora_hostgroups
| mysql_collations
| mysql_firewall_whitelist_rules
| mysql_firewall_whitelist_sqli_fingerprints
| mysql_firewall_whitelist_users
| mysql_galera_hostgroups
| mysql_group_replication_hostgroups
| mysql_query_rules
| mysql_query_rules_fast_routing
| mysql_replication_hostgroups
| mysql_servers
| mysql_users
| proxysql_servers
| restapi_routes
| runtime_checksums_values
| runtime_global_variables
| runtime_mysql_aws_aurora_hostgroups
| runtime_mysql_firewall_whitelist_rules
| runtime_mysql_firewall_whitelist_sqli_fingerprints
| runtime_mysql_firewall_whitelist_users
| runtime_mysql_galera_hostgroups
| runtime_mysql_group_replication_hostgroups
| runtime_mysql_query_rules
| runtime_mysql_query_rules_fast_routing
| runtime_mysql_replication_hostgroups
| runtime_mysql_servers
| runtime_mysql_users
| runtime_proxysql_servers
| runtime_restapi_routes
| runtime_scheduler
| scheduler
+-----------------------------------------------------------------+
32 rows in set (0.00 sec)
-- 表名以runtiem_开头的表示proxySQL服务中当前运行的配置内容,不能直接修改,不带runtime是下文图中mem相关的配置

ProxySQL管理接口的多层配置关系:

图片

ProxySQL整套配置系统分为三层: 第一层:RUNTIME: 代表proxySQL当前正在使用的配置,无法直接修改此配置,必须要从下一层(MEM层)load加载进来; 第二层:MEMORY(主要修改的配置表) memory层上面连接runtime层,下面连接disk持久化存储层; 在这层可以在线操作ProxySQL配置,随意进行修改,不会影响生产环境,确认正常之后再加载到runtime和持久化保存到磁盘上 具体修改操作方法为:insert、update、delete、select; 第三层:DISK/CFG FILE 持久化配置信息,重启时可以从磁盘快速加载回来; ProxySQL不同层次间移动配置信息: 为了将配置持久化到磁盘或者应用到runtime,在管理接口下有一系列管理命令来实现相关功能配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 01 user相关配置
LOAD MYSQL USERS TO RUNTIME;
-- MEM加载到runtime
SAVE MYSQL USERS TO MEMORY;
-- RUNTIME保存至MEM
LOAD MYSQL USERS FROM DISK;
-- DISK加载到MEM
SAVE MYSQL USERS TO DISK;
-- MEM保存至DISK
LOAD MYSQL USERS FROM CONFIG
-- CFG加载到MEM
# 02 server相关配置
LOAD MYSQL SERVERS TO RUNTIME;
-- MEM加载到RUNTIME
SAVE MYSQL SERVERS TO MEMORY;
-- RUNTIME保存至MEM
LOAD MYSQL SERVERS FROM DISK;
-- DISK加载到MEM
SAVE MYSQL SERVERS TO DISK;
-- MEM保存至DISK
LOAD MYSQL SERVERS FROM CONFIG
-- CFG加载到MEM
# 03 MYSQL QUERY RULES相关配置
LOAD MYSQL QUERY RULES TO RUNTIME;
-- MEM加载到RUNTIME
SAVE MYSQL QUERY RULES TO MEMORY;
-- RUNTIME保存至MEM
LOAD MYSQL QUERY RULES FROM DISK;
-- DISK加载到MEM
SAVE MYSQL QUERY RULES TO DISK;
-- MEM保存至DISK
LOAD MYSQL QUERY RULES FROM CONFIG
-- CFG加载到MEM
# 03 MYSQL VARIABLES相关配置
LOAD MYSQL VARIABLES TO RUNTIME;
-- MEM加载到RUNTIME
SAVE MYSQL VARIABLES TO MEMORY;
-- RUNTIME保存至MEM
LOAD MYSQL VARIABLES FROM DISK;
-- DISK加载到MEM
SAVE MYSQL VARIABLES TO DISK;
-- MEM保存至DISK
LOAD MYSQL VARIABLES FROM CONFIG
-- CFG加载到MEM

需要注意:只有load到runtime状态时才会验证配置,在保存到mem或disk时,都不会发生任何警告或错误; 当load到runtime时,如果出现了错误信息,将恢复为之前保存的状态,这时可以根据错误日志信息做检查;

总结:日常配置过程大部分时间是在mem中进行配置,然后load到runtime,或者save到disk中,对于cfg很少使用; ProxySQL基于SQL语句进行读写分离实践配置: ①. 在mysql_replication_hostgroup表中,配置读写组编号: proxySQL会根据server的read only的取值将服务器进行分组: read_only=0的server,即master会被分到编号为10的写组; read_only=1的server,即slave会被分到编号为20的读组;(所以需要将从库设置:set global read_only=1 )

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
db03 [(none)]>insert into mysql_replication_hostgroups(writer_hostgroup,reader_hostgroup,comment) values(10,20,'proxy');
Quer y OK, 1 row affected (0.00 sec)
db03 [(none)]>save mysql servers to disk;
Quer y OK, 0 rows affected (0.01 sec)
db03 [(none)]>load mysql servers to runtime;
Quer y OK, 0 rows affected (0.00 sec)
db03 [(none)]>select * from mysql_replication_hostgroups\G
*************************** 1. row ***************************
writer_hostgroup: 10
reader_hostgroup: 20
check_type: read_only
comment: proxy
1 row in set (0.00 sec)

② 添加主机到ProxySQL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
db03 [(none)]>insert into mysql_servers(hostgroup_id,hostname,port) values (10,'192.168.30.110',3306);
Quer y OK, 1 row affected (0.00 sec)
db03 [(none)]>insert into mysql_servers(hostgroup_id,hostname,port) values (20,'192.168.30.102',3306);
Quer y OK, 1 row affected (0.00 sec)
db03 [(none)]>insert into mysql_servers(hostgroup_id,hostname,port) values (20,'192.168.30.103',3306);
Quer y OK, 1 row affected (0.00 sec)
db03 [(none)]>save mysql servers to disk;
Quer y OK, 0 rows affected (0.01 sec)
db03 [(none)]>load mysql servers to runtime;
Quer y OK, 0 rows affected (0.00 sec)
db03 [(none)]>select * from mysql_servers\G;
*************************** 1. row ***************************
hostgroup_id: 20
hostname: 192.168.30.102
port: 3306
gtid_port: 0
status: ONLINE
weight: 1
compression: 0
max_connections: 1000
max_replication_lag: 0
use_ssl: 0
max_latency_ms: 0
comment:
*************************** 2. row ***************************
hostgroup_id: 20
hostname: 192.168.30.103
port: 3306
gtid_port: 0
status: ONLINE
weight: 1
compression: 0
max_connections: 1000
max_replication_lag: 0
use_ssl: 0
max_latency_ms: 0
comment:
*************************** 3. row ***************************
hostgroup_id: 10
hostname: 192.168.30.110
port: 3306
gtid_port: 0
status: ONLINE
weight: 1
compression: 0
max_connections: 1000
max_replication_lag: 0
use_ssl: 0
max_latency_ms: 0
comment:
3 rows in set (0.00 sec)

③ 创建监控用户,并开启监控 利用监控用户对后端节点的运行情况进行监控数据同步,一旦后端节点出现数据同步异常,就不要再向故障节点发送相应业务请求;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 主库创建监控用户
db01 [(none)]>create user monitor@'%' identified with mysql_native_password by '123';
Quer y OK, 0 rows affected (0.02 sec)
db01 [(none)]>grant replication client on *.* to monitor@'%';
Quer y OK, 0 rows affected (0.01 sec)
# proxysql中修改variables表配置信息
db03 [(none)]>set mysql-monitor_username='monitor';
Quer y OK, 1 row affected (0.00 sec)
db03 [(none)]>set mysql-monitor_password='123';
Quer y OK, 1 row affected (0.00 sec)
-- 以上变量信息修改为方法一
db03 [(none)]>update global_variables set variable_value='monitor' where variable_name='mysql-monitor_username';
Quer y OK, 1 row affected (0.00 sec)
db03 [(none)]>update global_variables set variable_value='123' where variable_name='mysql-monitor_password';
Quer y OK, 1 row affected (0.00 sec)
-- 以上变量信息修改为方法一
db03 [(none)]>load mysql variables to runtime;
Quer y OK, 0 rows affected (0.01 sec)
db03 [(none)]>save mysql variables to disk;
Quer y OK, 154 rows affected (0.00 sec)
# 检查核实配置信息
db03 [(none)]>select @@mysql-monitor_username\G
*************************** 1. row ***************************
@@mysql-monitor_username: monitor
1 row in set (0.00 sec)
db03 [(none)]>select @@mysql-monitor_password\G
*************************** 1. row ***************************
@@mysql-monitor_password: 123
1 row in set (0.00 sec)
# 查询监控日志信息
db03 [(none)]>select * from mysql_server_connect_log;
+-------------------+------+-------------------------+---------------------------------+----------------------------------------+
| hostname          | port | time_start_us          | connect_success_time_us | connect_error                             |
+-------------------+------+-------------------------+---------------------------------+----------------------------------------+
| 192.168.30.110 | 3306 | 1674026545375939 | 2831                                     | NULL                                             |
| 192.168.30.103 | 3306 | 1674026546137911 | 1480                                     | NULL                                             |
| 192.168.30.102 | 3306 | 1674026546899730 | 3781                                     | NULL                                             |
-- 检查确认所有节点的连接访问情况
db03 [(none)]>select * from mysql_server_ping_log;
+-------------------+------+-------------------------+-----------------------------+---------------+
| hostname          | port | time_start_us          | ping_success_time_us | ping_error |
+-------------------+------+-------------------------+-----------------------------+---------------+
| 192.168.30.102 | 3306 | 1674026696004217 | 1139                               | NULL           |
| 192.168.30.103 | 3306 | 1674026696095455 | 194                                 | NULL           |
| 192.168.30.110 | 3306 | 1674026696186794 | 1466                               | NULL           |
-- 检查确认所有节点的网络连通情况
db03 [(none)]>select * from mysql_server_read_only_log limit 3;
+-------------------+------+-------------------------+----------------------+-------------+--------+
| hostname          | port | time_start_us          | success_time_us | read_only | error  |
+-------------------+------+-------------------------+----------------------+-------------+--------+
| 192.168.30.110 | 3306 | 1674027579464285 | 1325                      | 0                | NULL  |
| 192.168.30.102 | 3306 | 1674027579479777 | 1743                      | 1                | NULL  |
| 192.168.30.103 | 3306 | 1674027579494993 | 308                        | 1                | NULL  |
-- 检查确认所有节点的只读状态信息(获取主库或从库主机信息)
db03 [(none)]>select * from mysql_server_replication_lag_log;
Empty set (0.00 sec)
-- 检查确认所有节点的主从延时情况

④ 创建应用用户信息 创建数据库应用用户信息,利用应用用户,可以使proxySQL进行数据库节点的操作管理;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 主库创建应用用户
db01 [(none)]>create user root@'%' identified with mysql_native_password by '123';
Quer y OK, 0 rows affected (0.00 sec)
db01 [(none)]>grant all on *.* to root@'%';
Quer y OK, 0 rows affected (0.00 sec)
# proxysql中添加数据库节点的管理用户信息
db03 [(none)]>insert into mysql_users(username,password,default_hostgroup) values('root','123',10);
Quer y OK, 1 row affected (0.00 sec)
db03 [(none)]>load mysql users to runtime;
Quer y OK, 0 rows affected (0.00 sec)
db03 [(none)]>save mysql users to disk;
Quer y OK, 0 rows affected (0.00 sec)
# 早期版本,需要开启事务的持续化(忽略)
update mysql_users set transaction_persistent=1 where username='root';
load mysql users to runtime;
save mysql users to disk;
-- 事务路由分配持续性,同一个事务的语句不会被分配到不同的组

⑤ 实用的读写规则配置

1
2
3
4
5
> insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (1,1,'^select.*for update$',10,1);
> insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (2,1,'^select',20,1);
-- 其余数据库操作语句信息,默认路由放置到主节点进行执行
> load mysql query rules to runtime;
> save mysql query rules to disk;

select … for update规则的rule_id必须要小于普通的select规则的rule_id,proxySQL是根据rule_id的顺序进行规则匹配的; ⑥ 测试读写分离效果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@xiaoQ-03 ~]# mysql -uroot -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit"
+-----------------+
| @@server_id |
+-----------------+
|                   51 |
+-----------------+
-- 非查询操作走的是主节点
[root@xiaoQ-03 ~]# mysql -uroot -p123 -P6033 -h127.0.0.1 -e "select @@server_id;"
+-----------------+
| @@server_id |
+-----------------+
|                   52 |
+-----------------+
[root@xiaoQ-03 ~]# mysql -uroot -p123 -P6033 -h127.0.0.1 -e "select @@server_id;"
+-----------------+
| @@server_id |
+-----------------+
|                    53 |
+-----------------+
-- 查询操作走的是从节点
>select * from stats_mysql_query_digest\G
-- 这个表对于分析SQL语句至关重要,是分析语句性能、定制路由规则指标的最主要来源

读写分离配置过程总结:

步骤操作说明涉及数据表信息涉及操作信息
01设置从库只读模式read_only=1
02添加主机组信息mysql_replication_hostgroups
03添加主机组节点信息mysql_servers
global_variables
04添加用户信息(监控用户 应用用户)
mysql_users
05添加读写分离规则mysql_query_rules

步骤四:读写分离架构软件配置扩展 ① 基于端口进行读写分离路由

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 修改proxySQL监听SQL流量的端口号,监听多端口信息
> set mysql-interfaces='0.0.0.0:6033;0.0.0.0:6034'
# 使监听端口配置信息生效
> save mysql variables to disk;
[root@xiaoQ-03 ~]# systemctl restart proxysql
# 设定相应读写分离路由规则
> delete from mysql_query_rules;
-- 为了测试效果,先清空已有规则信息
> insert into mysql_query_rules(rule_id,active,proxy_port,destination_hostgroup,apply) values(1,1,6033,10,1),(2,1,6034,20,1);
> load mysql query rules to runtime;
> save mysql query rules to disk;
-- 除了基于端口进行分离,还可以基于监听地址(修改字段proxy_addr即可),也可以基于客户端地址(修改字段client_addr字段即可);

② 基于用户进行读写分离路由

1
2
3
4
5
6
7
8
> insert into mysql_users(username,password,default_hostgroup) values ('write','123',10),('reader','123',20);
> load mysql users to runtime;
> save mysql users to disk;
> delete from mysql_query_rules;
-- 为了测试效果,先清空已有规则信息
> insert into mysql_query_rules(rule_id,active,username,destination_hostgroup,apply) values (1,1,'write',10,1),(2,1,'reader',20,1);
> load mysql users to runtime;
> save mysql users to disk;

1.18 数据库服务分布架构(MyCAT)

1.18.1 数据库服务分布架构概述介绍

分布式架构理念:(基于业务逻辑分布式/基于程序逻辑分布式) 架构演变过程早期,为了满足主要业务功能需求,可以将所有程序部署在一个服务器节点上; 架构演变过程发展,为了满足主要业务压力增长,可以将所有程序拆分部署在不同服务器上; 架构演变过程发展,为了满足主要业务安全稳定,可以将数据库设计成主从架构或读写分离; 架构演变过程发展,为了满足多个业务数量增加,可以将架构环境根据业务的情况独立拆分; 架构演变过程发展,为了满足单独业务数量激增,可以将多个数据表进行拆分到多个节点上;(垂直拆分-MyCAT进行数据表信息整合) 架构演变过程发展,为了满足单独业务数量激增,可以将单个数据表进行拆分到多个节点上;(水平拆分-MyCAT进行数据表信息整合) 架构演变过程发展,为了满足业务的数据搜索业务需求、缓存业务需求、大数据业务分析需求,还要引入NOSQL或NewSQL数据库; 传统网站架构的发展变化历程:

图片

图片

数据库存储架构发展变化历程:

图片

图片

1.18.2 数据库服务分布架构部署过程

01 MyCAT分布式存储基础环境准备: 基础环境架构规划:

主机名称地址信息端口信息数据库软件
db01192.168.30.1013307~3310(4个多实例-分两组)MySQL-8.26
db02192.168.30.1023307~3310(4个多实例-分两组)MySQL-8.26

基础环境架构图示:

图片

基础环境操作命令:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# 删除历史数据库环境(所有节点均操作)
[root@xiaoQ ~]# pkill mysqld
[root@xiaoQ ~]# rm -rf /data/330*
[root@xiaoQ ~]# \mv /etc/my.cnf /etc/my.cnf.bak
# 创建相关目录初始化数据(所有节点均操作)
[root@xiaoQ ~]# mkdir /data/33{07..10}/data -p && chown -R mysql.mysql /data/*
[root@xiaoQ ~]# mysqld --initialize-insecure --user=mysql --datadir=/data/3307/data --basedir=/usr/local/mysql
[root@xiaoQ ~]# mysqld --initialize-insecure --user=mysql --datadir=/data/3308/data --basedir=/usr/local/mysql
[root@xiaoQ ~]# mysqld --initialize-insecure --user=mysql --datadir=/data/3309/data --basedir=/usr/local/mysql
[root@xiaoQ ~]# mysqld --initialize-insecure --user=mysql --datadir=/data/3310/data --basedir=/usr/local/mysql
# 准备配置文件和启动脚本(DB-01)
[root@xiaoQ ~]# cat >/data/3307/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
port=3307
log-error=/data/3307/mysql.log
log_bin=/data/3307/mysql-bin
binlog_format=row
skip-name-resolve
server-id=7
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3307实例配置文件信息
[root@xiaoQ ~]# cat >/data/3308/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3308/data
socket=/data/3308/mysql.sock
port=3308
log-error=/data/3308/mysql.log
log_bin=/data/3308/mysql-bin
binlog_format=row
skip-name-resolve
server-id=8
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3308实例配置文件信息
[root@xiaoQ ~]# cat >/data/3309/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3309/data
socket=/data/3309/mysql.sock
port=3309
log-error=/data/3309/mysql.log
log_bin=/data/3309/mysql-bin
binlog_format=row
skip-name-resolve
server-id=9
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3309实例配置文件信息
[root@xiaoQ ~]# cat >/data/3310/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3310/data
socket=/data/3310/mysql.sock
port=3310
log-error=/data/3310/mysql.log
log_bin=/data/3310/mysql-bin
binlog_format=row
skip-name-resolve
server-id=10
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3310实例配置文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3307.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
LimitNOFILE=5000
EOF
-- 3307实例启动文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3308.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
LimitNOFILE=5000
EOF
-- 3308实例启动文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3309.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
LimitNOFILE=5000
EOF
-- 3309实例启动文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3310.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf
LimitNOFILE=5000
EOF
-- 3310实例启动文件信息
# 准备配置文件和启动脚本(DB-02)
[root@xiaoQ ~]# cat >/data/3307/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
port=3307
log-error=/data/3307/mysql.log
log_bin=/data/3307/mysql-bin
binlog_format=row
skip-name-resolve
server-id=17
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3307实例配置文件信息
[root@xiaoQ ~]# cat >/data/3308/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3308/data
socket=/data/3308/mysql.sock
port=3308
log-error=/data/3308/mysql.log
log_bin=/data/3308/mysql-bin
binlog_format=row
skip-name-resolve
server-id=18
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3308实例配置文件信息
[root@xiaoQ ~]# cat >/data/3309/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3309/data
socket=/data/3309/mysql.sock
port=3309
log-error=/data/3309/mysql.log
log_bin=/data/3309/mysql-bin
binlog_format=row
skip-name-resolve
server-id=19
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3309实例配置文件信息
[root@xiaoQ ~]# cat >/data/3310/my.cnf<<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/data/3310/data
socket=/data/3310/mysql.sock
port=3310
log-error=/data/3310/mysql.log
log_bin=/data/3310/mysql-bin
binlog_format=row
skip-name-resolve
server-id=20
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF
-- 3310实例配置文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3307.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
LimitNOFILE=5000
EOF
-- 3307实例启动文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3308.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
LimitNOFILE=5000
EOF
-- 3308实例启动文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3309.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
LimitNOFILE=5000
EOF
-- 3309实例启动文件信息
[root@xiaoQ ~]# cat >/etc/systemd/system/mysqld3310.ser vice<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Ser vice]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf
LimitNOFILE=5000
EOF
-- 3310实例启动文件信息
# 启动数据库多实例程序(所有节点均操作)
[root@xiaoQ ~]# systemctl daemon-reload
[root@xiaoQ ~]# systemctl start mysqld3307
[root@xiaoQ ~]# systemctl start mysqld3308
[root@xiaoQ ~]# systemctl start mysqld3309
[root@xiaoQ ~]# systemctl start mysqld3310
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "show variables like 'server_id'"
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "show variables like 'server_id'"
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "show variables like 'server_id'"
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "show variables like 'server_id'"

02 MyCAT分布式存储主从环境构建: 进行多实例主从环境的主从与双主的架构构建:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# 实现红色线条数据主从关系同步
# 实现双主关系建立(192.168.30.101:3307 <---> 192.168.30.102:3307)
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "create user repl@'192.168.30.%' identified with mysql_native_password by '123';grant replication slave on *.*
to repl@'192.168.30.%';"
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "create user root@'192.168.30.%' identified with mysql_native_password by '123';grant all on *.* to
root@'192.168.30.%';"
-- 在DB02数据库-192.168.30.102上进行操作
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "change master to master_host='192.168.30.102',
master_port=3307,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB01数据库-192.168.30.101上进行操作
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "change master to master_host='192.168.30.101',
master_port=3307,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB02数据库-192.168.30.102上进行操作
# 实现主从关系建立(192.168.30.101:3307 ---> 192.168.30.101:3309)
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "change master to master_host='192.168.30.101',
master_port=3307,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB01数据库-192.168.30.101上进行操作
# 实现主从关系建立(192.168.30.102:3307 ---> 192.168.30.102:3309)
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "change master to master_host='192.168.30.102',
master_port=3307,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB02数据库-192.168.30.102上进行操作
# 实现红色线条数据主从关系同步
# 实现双主关系建立(192.168.30.101:3308 <---> 192.168.30.102:3308)
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "create user repl@'192.168.30.%' identified with mysql_native_password by '123';grant replication slave on *.*
to repl@'192.168.30.%';"
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "create user root@'192.168.30.%' identified with mysql_native_password by '123';grant all on *.* to
root@'192.168.30.%';"
-- 在DB01数据库-192.168.30.101上进行操作
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "change master to master_host='192.168.30.101',
master_port=3308,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB02数据库-192.168.30.102上进行操作
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "change master to master_host='192.168.30.102',
master_port=3308,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB01数据库-192.168.30.101上进行操作
# 实现主从关系建立(192.168.30.101:3308 ---> 192.168.30.101:3310)
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "change master to master_host='192.168.30.101',
master_port=3308,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB01数据库-192.168.30.101上进行操作
# 实现主从关系建立(192.168.30.102:3308 ---> 192.168.30.102:3310)
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "change master to master_host='192.168.30.102',
master_port=3308,master_auto_position=1,master_user='repl',master_password='123';"
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "start slave;"
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "show slave status\G;"|grep Running;
-- 在DB02数据库-192.168.30.102上进行操作
# 核实检查主从状态
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "show slave status\G;"|grep Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "show slave status\G;"|grep Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "show slave status\G;"|grep Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "show slave status\G;"|grep Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
-- 在db01 db02数据库上均做检查
# 异常同步错误重置方法(特殊情况执行)
[root@xiaoQ ~]# mysql -S /data/3307/mysql.sock -e "stop slave;reset slave all;"
[root@xiaoQ ~]# mysql -S /data/3308/mysql.sock -e "stop slave;reset slave all;"
[root@xiaoQ ~]# mysql -S /data/3309/mysql.sock -e "stop slave;reset slave all;"
[root@xiaoQ ~]# mysql -S /data/3310/mysql.sock -e "stop slave;reset slave all;"

03 MyCAT分布式存储服务安装部署: MyCAT是开源组织和社区开发人员,在淘宝cober(TDDL)基础上进行的二次开发; 软件下载链接地址:http://dl.mycat.org.cn/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 预先安装java运行环境(在主节点进行操作)
[root@xiaoQ ~]# yum install -y java
# 上传解压mycat程序包
[root@xiaoQ ~]# cd /usr/local
[root@xiaoQ ~]# ll
-rw-r--r--   1 root root    2068371 1月  28 22:05 Mycat-server-1.6.7.4-release-20200105164103-linux\ .tar.gz
-rw-r--r--   1 root root    3956740 1月  28 22:05 mysql-connector-java-8.0.21.tar.gz
[root@xiaoQ ~]# tar xf Mycat-server-1.6.7.4-release-20200105164103-linux\ .tar.gz
[root@xiaoQ ~]# tar xf mysql-connector-java-8.0.21.tar.gz
# 配置服务程序环境变量
[root@xiaoQ ~]# vim /etc/profile
export PATH=/usr/local/mysql/bin:/usr/local/mysqlsh/bin:/usr/local/mysql-router/bin:$PATH
export PATH=/usr/local/mycat/bin:$PATH
[root@xiaoQ ~]# source /etc/profile
# 运行启动服务程序并测试连接mycat:
[root@xiaoQ ~]# mycat start
[root@xiaoQ ~]# mysql -uroot -p123456 -h 127.0.0.1 -P8066
或者
[root@xiaoQ ~]# mysql -uroot -p123456 -h 127.0.0.1 -P8066 --default-auth=mysql_native_password
-- 有可能会出现连接不上的情况,因为mycat程序库中,使用的java连接驱动器版本为5.1版本,和数据库8.0可能有兼容问题
[root@xiaoQ ~]# cp mysql-connector-java-8.0.21/mysql-connector-java-8.0.21. jar /usr/local/mycat/lib/
[root@xiaoQ ~]# mycat restart
-- 可以进行mycat连接驱动更新操作,可以解决mycat连接问题

04 MyCAT分布式存储读写分离实现 对mycat进行功能配置操作前,需要先了解mycat程序的目录结构:

目录信息解释说明文件信息解释说明
bin程序脚本目录
管理节点信息配置文件(主配置文件)
conf配置文件目录schema.xml
节点信息、读写分离、高可用设置、调用分片策略…
rule.xml定义分片规则配置文件(分片策略定义、功能使用方法)
服务功能本身配置文件(服务有关配置)
server.xml
用户、网络、权限、策略、资源…
xx.txt分片参数定义文件
log4j2.xml相关日志记录配置
lib驱动程序目录
logs日志文件目录wrapper.log服务运行启动日志文件
mycat.log服务运行情况日志文件

mycat服务核心应用配置说明: 01 配置文件信息说明:schema.xml(实现读写分离)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[root@master ~]# cd /usr/local/mycat/conf/
[root@master conf ]# cp schema.xml schema.xml.bak
[root@master conf ]# vim schema.xml
# 逻辑库
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
</schema>
-- 主要用于展现给客户端应用程序的库信息,可以被客户端访问使用
-- 在访问testdb逻辑数据库时,实际上是在访问dn1数据节点中的数据;
# DN数据节点:逻辑分片(分片定义)
<dataNode name="dn1" dataHost="localhost1" database="world" />
-- 访问dn1节点,等价于访问localhost1数据主机,访问数据主机上的world数据库;
-- 在此步配置上,可以实现数据库业务垂直拆分和水平拆分;
# DH数据主机(节点定义)
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="192.168.30.101:3307" user="root" password="123">
<readHost host="db2" url="192.168.30.101:3309" user="root" password="123">
</writeHost>
</dataHost>
-- 访问localhost1等价于访问后端的db1和db2,即具体的后端数据库节点信息
-- 在此步骤配置上,可以实现高可用和读写分离功能

schema.xml配置文件模板信息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http:// io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="world" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="192.168.30.101:3307" user="root" password="123">
<readHost host="db2" url="192.168.30.101:3309" user="root" password="123" />
</writeHost>
</dataHost>
</mycat:schema>

mycat服务中schema.xml配置文件信息参数详述:(读写分离和高可用配置功能实现后讲解) 01 schema区域配置部分:

配置参数配置方法解释说明
checkSQLschemacheckSQLschema=true表示检查是否使用数据库.表的方式调取数据信息
checkSQLschema=false表示忽略检查使用数据库.表的方式调取数据信息(默认已经进入到指定库中了)
sqlMaxLimit数值信息表示实现分片功能的行数限制(也可以理解为是分页功能)
dataNode字符信息表示逻辑数据库需要连接访问的后端节点信息

02 dataNode区域配置部分:

配置参数配置方法解释说明
name字符信息表示自定义的后端节点名称(与schema中的dataNode配置要相同)
dataHost字符信息表示自定义的后端主机组或实例组名称
database字符信息表示指定需要访问后端的真实数据库信息

03 dataHost区域配置部分:

配置参数配置方法解释说明
name字符信息表示自定义的后端主机组或实例组名称(与dataNode中的dataHost配置要相同)
maxCon数值信息表示服务承载的最大并发连接数(单节点 写-500100 读-100010000)
minCon表示数值信息当释在数服务预先准备的连接池数量,当服务启动之后,在后端节点上自动开启的连接线程放连接资源的最低值,预先准备好连接资源可以减少CPU计算压力据库主节点上,可以使用show processlist命令查询到,已经准备好的sleep连接信息(通常20~50)
balance表示当数当数指定数值简述:当双主双从模式(M1-S1,M2-S2,M1与M2互为主备),M2 S1 S2都参与select语句的负载当数指定读操作的负载均衡类型,目前的应用取值有三种:值为0,不开启读写分离机制,所有读操作都发送到当前可用的writeHost上;值为1,全部的readHost与standby writeHost参与select语句的负载均衡值为2,所有读操作都随机的在writeHost、readHost上分发
writeType表示当数布尔信息重新当数指定写操作的负载均衡类型,目前的应用取值有两种:值为0时,所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost启动后已切换后的为主,切换信息记录在配置文件中(dnindex.properties)值为1时,所有写操作都随机的发送到配置writeHost节点上(不推荐使用)
switchType表示当数数值信息当数当数主节点故障切换的方式设定值为-1时,表示不自动切换;值为1时,表示默认值设置,会实现自动切换;值为2时,基于mysql主从同步的状态决定是否切换,心跳语句为show slave status,进行datahost切换
tempReadHostAvailable当数可以布尔信息当数可以值设置为1时,表示1主1从时(1个writehost,1个readhost时)开启此参数,表示写节点故障时,对应读节点依然可以正常工作;值设置为0时,如果2主2从时(2个writehost,2个readhost时)关闭此参数,表示写节点故障时,对应读节点随之停止正常工作;

mycat读写分离测试环境准备:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 在db01-3307主节点进行操作
[root@master ~]# mysql -S /data/3307/mysql.sock -e "create user root@'10.0.0.%' identified by 123;grant all on *.* to root@'10.0.0.%';"
[root@master ~]# mysql -S /data/3307/mysql.sock -e "source /root/world-db/world.sql"
# 在db01-3308主节点进行操作
[root@master ~]# mysql -S /data/3308/mysql.sock -e "create user root@'10.0.0.%' identified by 123;grant all on *.* to root@'10.0.0.%';"
[root@master ~]# mysql -S /data/3308/mysql.sock -e "source /root/world-db/world.sql"
[root@master ~]# mycat restart
# 读写分离测试操作
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           9 |
+-------------+
1 row in set (0.05 sec)
-- 测试读效果
mysql> begin;select @@server_id;commit;
+-------------+
| @@server_id |
+-------------+
|           7 |
+-------------+
1 row in set (0.00 sec)
-- 测试写效果

05 MyCAT分布式存储冗余功能实现 利用mycat分布式存储功能配置,实现读写分离及高可用效果: 利用mycat分布式存储功能配置,实现读写分离及高可用效果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@master conf ]# mv schema.xml schema.xml.rw
[root@master conf ]# vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http:// io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
</schema>
<dataNode name="sh1" dataHost="xiaoq1" database="world" />
<dataHost name="xiaoq1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="192.168.30.101:3307" user="root" password="123">
<readHost host="db2" url="192.168.30.101:3309" user="root" password="123" />
</writeHost>
<writeHost host="db3" url="192.168.30.102:3307" user="root" password="123">
<readHost host="db4" url="192.168.30.102:3309" user="root" password="123" />
</writeHost>
</dataHost>
</mycat:schema>
-- 在利用2组高可用(4个节点)实现的两主两从的环境中,默认第一个写节点为写,其余节点都为从,出现故障时才切换
-- 当检测主节点心跳状态出现异常时,对应read节点配置也会失效,第二个写节点接管主节点工作,实现故障转移
-- primary writehost:负责写操作的节点
-- standby writehost:和读节点一样,只提供读服务(默认)
-- 当写节点宕机后,后面跟的readhost也不提供服务,这时候standby的writehost就提供写服务,后面readhost提供读服务

mycat读写分离高可用功能测试:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# db01主节点进行操作
[root@master ~]# mycat restart
# 读写分离测试操作
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           9 |
+-------------+
1 row in set (0.04 sec)
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|          19 |
+-------------+
1 row in set (0.00 sec)
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           9 |
+-------------+
1 row in set (0.00 sec)
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|          17 |
+-------------+
1 row in set (0.00 sec)
-- 测试读效果
mysql> begin;select @@server_id;commit;
Quer y OK, 0 rows affected (0.00 sec)
+-------------+
| @@server_id |
+-------------+
|           7 |
+-------------+
1 row in set (0.00 sec)
-- 测试写效果
# 高可用测试操作
[root@master conf ]# systemctl stop mysqld3307
[root@master conf ]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|          19 |
+-------------+
1 row in set (0.00 sec)
-- 测试读效果(故障转移后)
mysql> begin;select @@server_id;commit;
Quer y OK, 0 rows affected (0.00 sec)
+-------------+
| @@server_id |
+-------------+
|          17 |
+-------------+
1 row in set (0.00 sec)
-- 测试写效果(故障转移后)
[root@master conf ]# systemctl start mysqld3307
[root@master conf ]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
-- 故障复原修复后的情况
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|          19 |
+-------------+
1 row in set (0.01 sec)
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           7 |
+-------------+
1 row in set (0.00 sec)
mysql>  select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           9 |
+-------------+
1 row in set (0.00 sec)
mysql> begin;select @@server_id;commit;
+-------------+
| @@server_id |
+-------------+
|          17 |
+-------------+
1 row in set (0.01 sec)
-- 高可用故障修复后,原有主节点不会抢占现有节点的写资源;

06 MyCAT分布式存储企业场景应用 场景应用一:垂直分表应用 模拟的应用场景:淘宝网站业务应用到 user表(sh1)、order_t表(sh2)、others(sh3)

说明:为了便于简化理解配置过程,以及整体的垂直分表的配置思路,仅实现user和order_t两个表的垂直划分即可;

图片

步骤一:编写服务程序配置信息;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@master ~]# cd /usr/local/mycat/conf/
[root@master conf ]# mv schema.xml schema.xml.ha
[root@master conf ]# vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http:// io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
<table name="user" dataNode="sh1" />
<table name="order_t" dataNode="sh2" />
</schema>
<dataNode name="sh1" dataHost="xiaoq1" database="taobao" />
<dataNode name="sh2" dataHost="xiaoq2" database="taobao" />
<dataHost name="xiaoq1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="192.168.30.101:3307" user="root" password="123">
<readHost host="db2" url="192.168.30.101:3309" user="root" password="123" />
</writeHost>
<writeHost host="db3" url="192.168.30.102:3307" user="root" password="123">
<readHost host="db4" url="192.168.30.102:3309" user="root" password="123" />
</writeHost>
</dataHost>
<dataHost name="xiaoq2" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="192.168.30.101:3308" user="root" password="123">
<readHost host="db2" url="192.168.30.101:3310" user="root" password="123" />
</writeHost>
<writeHost host="db3" url="192.168.30.102:3308" user="root" password="123">
<readHost host="db4" url="192.168.30.102:3310" user="root" password="123" />
</writeHost>
</dataHost>
</mycat:schema>
-- 利用dataNode配置信息创建两个数据表垂直分片(分组),对应sh1和sh2
-- 垂直分片sh1负责将用户表信息,读写分离及高可用存储在 101-3307/3309 102-3307/3309节点上
-- 垂直分片sh2负责将订单表信息,读写分离及高可用存储在 101-3308/3310 102-3308/3310节点上

步骤二:测试服务程序应用效果;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 创建测试库和表
[root@master ~]# mysql -S /data/3307/mysql.sock -e "create database taobao charset utf8;"
[root@master ~]# mysql -S /data/3308/mysql.sock -e "create database taobao charset utf8;"
[root@master ~]# mysql -S /data/3307/mysql.sock -e "use taobao;create table user(id int,name varchar(20));"
[root@master ~]# mysql -S /data/3308/mysql.sock -e "use taobao;create table order_t(id int,name varchar(20));"
-- 对于数据库的DDL操作不要进入mycat进行操作,避免出现死锁问题,都需要进入后端节点进行操作
# 重启服务程序
[root@master ~]# mycat restart
# 创建数据表测试数据
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> insert into user values(1,'a');
mysql> insert into user values(2,'b');
mysql> insert into user values(3,'c');
mysql> commit;
-- 向用户表中添加模拟数据信息
mysql> insert into order_t values(1,'x'),(2,'y');
mysql> commit;
-- 向订单表中添加模拟数据信息
# 查看后端数据库节点数据存储信息
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "show tables from taobao;"
+------------------+
| Tables_in_taobao |
+------------------+
| user             |
+------------------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "show tables from taobao;"
+------------------+
| Tables_in_taobao |
+------------------+
| order_t          |
+------------------+
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "select * from taobao.user ;"
+------+------+
| id   | name |
+------+------+
|    1 | a    |
|    2 | b    |
|    3 | c    |
+------+------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "select * from taobao.order_t;"
+------+------+
| id   | name |
+------+------+
|    1 | x    |
|    2 | y    |
+------+------+

场景应用二:水平分表应用 在进行数据表水平拆分时需要考虑两个问题:水平拆分策略和拆分条件: 拆分策略:服务程序提供了很多种方案,其中可以根据最长用的range进行拆分,还有取模、枚举、日期、HASH… 几乎融合经典业务中大部分的分片策略,mycat已经开发了相应算法,非常方便调用 拆分条件:可以根据指定索引条件拆分,比如时间信息,订单编号,数据表id信息… 拆分条件就是作为分片条件的列,也称为分片键

图片

基于范围进行分片,模拟对数据库t3表进行拆分: 由于表中行数非常多,假设总共2000w行,其中11000w可以分片为sh1,1001w2000w可以分片为sh2; 并且数据表访问频繁,用户访问数据较为离散; 步骤一:编写服务程序配置信息; 修改schema.xml文件,定制分片策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@master ~]# cd /usr/local/mycat/conf/
[root@master conf ]# cp schema.xml schema.xml.bak01
[root@master conf ]# vim schema.xml
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
<table name="user" dataNode="sh1" />
<table name="order_t" dataNode="sh2" />
<table name="t3" dataNode="sh1,sh2" rule="auto-sharding-long" />
</schema>
-- 在schema区域配置中,添加t3表的水平分片配置信息,即t3表对应两个分片信息 sh1和sh2;
-- 利用rule参数选择调用的分片规则,即选择auto-sharding-long(范围分片)规则进行水平分片

修改rule.xml文件,定义和使用分片策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
[root@master conf ]# cp rule.xml rule.xml.bak
[root@master conf ]# vim rule.xml
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
-- 定义分片键(即分片条件列)
<algorithm>rang-long</algorithm>
-- 定义分片使用的算法
</rule>
</tableRule>
....
<function name="rang-long"
class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
-- 定义分片范围设定信息,需要加载autopartition-long.txt文件信息识别
</function>
-- 分片使用的算法函数信息

修改autopartition-long.txt,定义分片具体范围信息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@master conf ]# cp autopartition-long.txt autopartition-long.txt.bak
[root@master conf ]# vim autopartition-long.txt
# range start-end ,data node index
-- 设置分片范围(起点-终点),定义数据节点指针
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
-- 修改前默认配置,其中0 1 2 表示分片后的索引代码,类似于数组的下标信息
0-10=0
10-20=1
-- 修改后配置信息,简化后的模拟配置信息

步骤二:测试服务程序应用效果;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 创建测试数据表
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "use taobao;create table t3 (id int not null primary key auto_increment,name varchar(20) not null);"
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "use taobao;create table t3 (id int not null primary key auto_increment,name varchar(20) not null);"
# 重启服务程序
[root@master ~]# mycat restart
# 创建数据表测试数据
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> insert into t3(id,name) values(1,'a');
mysql> insert into t3(id,name) values(2,'b');
mysql> insert into t3(id,name) values(3,'c');
mysql> insert into t3(id,name) values(4,'d');
mysql> insert into t3(id,name) values(11,'aa');
mysql> insert into t3(id,name) values(12,'bb');
mysql> insert into t3(id,name) values(13,'cc');
mysql> insert into t3(id,name) values(14,'dd');
# 查看后端数据库节点数据存储信息
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "select * from taobao.t3;"
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "select * from taobao.t3;"
+----+------+
| id | name |
+----+------+
| 11 | aa   |
| 12 | bb   |
| 13 | cc   |
| 14 | dd   |
+----+------+

基于取模进行分片,模拟企业等值随机查找数据信息: 取模方式:分片键(一个列)与节点数量进行取余,得到余数后将数据写入对应节点中;

1
2
3
4
5
6
7
8
1%3 ~ 1
2%3 ~ 2
3%3 ~ 0
4%3 ~ 1
-- 任何正整数数字和N(正整数)取模,得到的值永远都是 0~N-1之间
# 实现基于id等值随机查询,可以利用取模分片
id % 分片数量取模
N % 5 = 0 ~ 4 idx

步骤一:编写服务程序配置信息; 修改schema.xml文件,定制分片策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@master ~]# cd /usr/local/mycat/conf/
[root@master conf ]# cp schema.xml schema.xml.bak02
[root@master conf ]# vim schema.xml
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
<table name="user" dataNode="sh1" />
<table name="order_t" dataNode="sh2" />
<table name="t4" dataNode="sh1,sh2" rule="mod-long" />
</schema>
-- 在schema区域配置中,添加t4表的水平分片配置信息,即t4表对应两个分片信息 sh1和sh2;
-- 利用rule参数选择调用的分片规则,即选mod-long(取模分片)规则进行水平分片

修改rule.xml文件,定义和使用分片策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
[root@master conf ]# cp rule.xml rule.xml.bak
[root@master conf ]# vim rule.xml
<tableRule name="mod-long">
<rule>
<columns>id</columns>
-- 定义分片键(即分片条件列)
<algorithm>mod-long</algorithm>
-- 定义分片使用的算法
</rule>
</tableRule>
....
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
-- 定义分片范围设定信息,基于两个分片进行取模运算
</function>
-- 分片使用的算法函数信息

步骤二:测试服务程序应用效果;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 创建测试数据表
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "use taobao;create table t4 (id int not null primary key auto_increment,name varchar(20) not null);"
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "use taobao;create table t4 (id int not null primary key auto_increment,name varchar(20) not null);"
# 重启服务程序
[root@master ~]# mycat restart
# 创建数据表测试数据
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> insert into t4(id,name) values(1,'a');
mysql> insert into t4(id,name) values(2,'b');
mysql> insert into t4(id,name) values(3,'c');
mysql> insert into t4(id,name) values(4,'d');
mysql> insert into t4(id,name) values(6,'x'),(8,'y'),(10,'z');
# 查看后端数据库节点数据存储信息
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "select * from taobao.t4;"
+----+------+
| id | name |
+----+------+
|  2 | b    |
|  4 | d    |
|  6 | x    |
|  8 | y    |
| 10 | z    |
+----+------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "select * from taobao.t4;"
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  3 | c    |
+----+------+

基于枚举进行分片,模拟企业跨地域区域存储和查找数据信息: 当一个企业分公司数量很多时,比如:北京分公司、天津分公司、上海分公司、甚至有国外分公司时; 不同区域的业务,访问对应区域的数据信息,实现数据信息根据区域不同分片存储; 创建区域划分的表信息(含有区域划分的列信息):t5表

idnametelnum
01bj1212
02sh2222
03bj1313
04sh3333
05bj1414

步骤一:编写服务程序配置信息; 修改schema.xml文件,定制分片策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@master ~]# cd /usr/local/mycat/conf/
[root@master conf ]# cp schema.xml schema.xml.bak03
[root@master conf ]# vim schema.xml
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
<table name="user" dataNode="sh1" />
<table name="order_t" dataNode="sh2" />
<table name="t5" dataNode="sh1,sh2" rule="sharding-by-intfile" />
</schema>
-- 在schema区域配置中,添加t5表的水平分片配置信息,即t5表对应两个分片信息 sh1和sh2;
-- 利用rule参数选择调用的分片规则,即选sharding-by-intfile(枚举分片)规则进行水平分片

修改rule.xml文件,定义和使用分片策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[root@master conf ]# cp rule.xml rule.xml.bak
[root@master conf ]# vim rule.xml
<tableRule name="sharding-by-intfile">
<rule>
<columns>name</columns>
-- 定义分片键(即分片条件列)
<algorithm>hash-int</algorithm>
-- 定义分片使用的算法
</rule>
</tableRule>
....
<function name="hash-int"
class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
-- 定义分片范围设定信息,需要加载partition-hash-int.txt文件信息识别
<property name="type">1</property>
-- 默认枚举分片只识别数字标识信息,需要修改类型为1,使之识别字符串枚举信息
</function>
-- 分片使用的算法函数信息

修改partition-hash-int.txt,定义分片具体范围信息:

1
2
3
4
5
6
7
8
9
[root@master conf ]# cp partition-hash-int.txt partition-hash-int.txt.bak
[root@master conf ]# vim partition-hash-int.txt
10000=0
10010=1
-- 修改前默认配置,根据指定标识信息进行分片
bj=0
sh=1
DEFAULT_NODE=1
-- 修改后配置信息,简化后的模拟配置信息

步骤二:测试服务程序应用效果;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 创建测试数据表
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "use taobao;create table t5 (id int not null primary key auto_increment,name varchar(20) not null);"
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "use taobao;create table t5 (id int not null primary key auto_increment,name varchar(20) not null);"
# 重启服务程序
[root@master ~]# mycat restart
# 创建数据表测试数据
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> insert into t5(id,name) values(1,'bj');
mysql> insert into t5(id,name) values(2,'sh');
mysql> insert into t5(id,name) values(3,'bj');
mysql> insert into t5(id,name) values(4,'sh');
mysql> insert into t5(id,name) values(5,'tj');
mysql> commit;
# 查看后端数据库节点数据存储信息
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "select * from taobao.t5;"
+----+------+
| id | name |
+----+------+
|  1 | bj   |
|  3 | bj   |
+----+------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "select * from taobao.t5;"
+----+------+
| id | name |
+----+------+
|  2 | sh   |
|  4 | sh   |
|  5 | tj   |
+----+------+

1.18.3 数据库服务分布架构高级功能

01 MyCAT服务全局表功能应用 全局表功能概念介绍: 假设在数据库中有一个t表,经常被其他数据表 a b c d …进行连表查询引用(join) 如果此时t表进行了分片存储处理,其他数据表和t表进行连表查询时,需要跨分片进行查询数据,那么查询代价将会非常的高; 因此需要将t表设置为全局表,即将t表数据写入到所有分片中,实现t表数据分片冗余的存储(存储多份); 全局表使用场景介绍: 如果业务中有些数据类似于数据字典,比如:配置文件的配置信息,常用业务的配置或者数量不大很少变动的表; 这些表往往不是特别大,而且大部分的业务场景都会用到,那么这种表适合于作为Mycat全局表,无须对数据进行切分; 要在所有的分片上保存一份数据即可,mycat 在join操作中,业务表与全局表进行join聚合会优先选择相同分片内的全局表join; 避免跨库join,在进行数据插入操作时,mycat把数据分发到全局表对应所有分片执行,进行数据读取时会随机获取一个节点读取数据

图片

步骤一:编写服务程序配置信息; 修改schema.xml文件,创建全局表信息:

1
2
3
4
5
6
7
8
9
[root@master ~]# cd /usr/local/mycat/conf/
[root@master conf ]# cp schema.xml schema.xml.bak04
[root@master conf ]# vim schema.xml
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
<table name="user" dataNode="sh1" />
<table name="order_t" dataNode="sh2" />
<table name="t_area" primaryKey="id" type="global" dataNode="sh1,sh2"  />
</schema>
-- 在schema区域配置中,添加t_area全局表配置信息,即t_area表对应两个分片信息 sh1和sh2;

步骤二:测试服务程序应用效果;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 创建测试数据表
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "use taobao;create table t_area (id int not null primary key auto_increment,name varchar(20) not null);"
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "use taobao;create table t_area (id int not null primary key auto_increment,name varchar(20) not null);"
# 重启服务程序
[root@master ~]# mycat restart
# 创建数据表测试数据
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> insert into t_area(id,name) values(1,'a');
mysql> insert into t_area(id,name) values(2,'b');
mysql> insert into t_area(id,name) values(3,'c');
mysql> insert into t_area(id,name) values(4,'d');
mysql> commit;
# 查看后端数据库节点数据存储信息
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "select * from taobao.t_area;"
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "select * from taobao.t_area;"
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+

02 MyCAT服务ER表功能应用 ER表功能概念介绍: 假设有两张数据表 a 和 b,需要经常进行连表查询,但a和b表的数据信息都做了水平分割,这样进行连表查询的代价也会很大; 为防止跨分片join,可以使用E-R模式,让被驱动表跟着驱动表的数据进行分片处理,使有关联的数据存储在一个分片中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 连表查询过程操作
a
join
b
on a.xx = b.yy
# 数据分片处理方案-数据a表
id    name
1      a                    -- 对应数据分片sh1
3      c
2      b                    -- 对应数据分片sh2
4      d
# 数据分片处理方案-数据b表
id        addr   aid
1001      bj      1                    -- 对应数据分片sh1
1002      sh     2
1003      tj      3                     -- 对应数据分片sh2
1004      wh    4

步骤一:编写服务程序配置信息; 修改schema.xml文件,创建E-R关联关系:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[root@master ~]# cd /usr/local/mycat/conf/
[root@master conf ]# cp schema.xml schema.xml.bak05
[root@master conf ]# vim schema.xml
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
<table name="user" dataNode="sh1" />
<table name="order_t" dataNode="sh2" />
<table name="a" dataNode="sh1,sh2" rule="mod-long_xiaoq">
<childTable name="b" joinKey="aid" parentKey="id" />
</table>
</schema>
-- 在schema区域配置中,添加a 和 b ER表配置信息,即a表对应两个分片信息与b表对应的分片信息有关联;

修改rule.xml文件,定义和使用分片策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[root@master conf ]# vim rule.xml
<tableRule name="mod-long_xiaoq">
<rule>
<columns>id</columns>
-- 定义分片键(即分片条件列)
<algorithm>mod-long_xiaoq</algorithm>
-- 定义分片使用的算法
</rule>
</tableRule>
....
<function name="mod-long_xiaoq" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
-- 定义分片范围设定信息,基于两个分片进行取模运算
</function>
-- 分片使用的算法函数信息

步骤二:测试服务程序应用效果;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 创建测试数据表
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "use taobao;create table a (id int not null primary key auto_increment,name varchar(20) not null);"
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "use taobao;create table b (id int not null primary key auto_increment,addr varchar(20) not null,aid int);"
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "use taobao;create table a (id int not null primary key auto_increment,name varchar(20) not null);"
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "use taobao;create table b (id int not null primary key auto_increment,addr varchar(20) not null,aid int);"
# 重启服务程序
[root@master ~]# mycat restart
# 创建数据表测试数据
[root@master ~]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> insert into a(id,name) values(1,'a');    --分片节点1   3308
mysql> insert into a(id,name) values(2,'b');    --分片节点0   3307
mysql> insert into a(id,name) values(3,'c');    --分片节点1   3308
mysql> insert into a(id,name) values(4,'d');    --分片节点0   3307
mysql> insert into a(id,name) values(5,'e');    --分片节点1   3308
mysql> insert into b(id,addr,aid) values(1001,'bj',1);    --分片节点1   3308
mysql> insert into b(id,addr,aid) values(1002,'sj',3);    --分片节点1   3308
mysql> insert into b(id,addr,aid) values(1003,'sd',4);    --分片节点0   3307
mysql> insert into b(id,addr,aid) values(1004,'we',2);    --分片节点0   3307
mysql> insert into b(id,addr,aid) values(1005,'er',5);    --分片节点1   3308
mysql> commit;
# 查看后端数据库节点数据存储信息
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "select * from taobao.a;"
+----+------+
| id | name |
+----+------+
|  2 | b    |
|  4 | d    |
+----+------+
[root@master conf ]# mysql -S /data/3307/mysql.sock -e "select * from taobao.b;"
+------+------+------+
| id   | addr | aid  |
+------+------+------+
| 1003 | sd   |    4 |
| 1004 | we   |    2 |
+------+------+------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "select * from taobao.a;"
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  3 | c    |
|  5 | e    |
+----+------+
[root@master conf ]# mysql -S /data/3308/mysql.sock -e "select * from taobao.b;"
+------+------+------+
| id   | addr | aid  |
+------+------+------+
| 1001 | bj   |    1 |
| 1002 | sj   |    3 |
| 1005 | er   |    5 |
+------+------+------+

1.18.4 数据库服务分布架构运行维护

01 基础管理操作-查询操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[root@master conf ]# mysql -uroot -p123456 -h 192.168.30.101 -P9066
mysql> show @@help;
-- 获取查看帮助信息
mysql> show @@server ;
-- 查看mycat服务状态情况
mysql> show @@datanode;
-- 查看分片信息情况
mysql> show @@datasource;
-- 查看数据源信息
mysql> reload @@config;
-- 重新加载配置信息-schema.xml
mysql> reload @@config_all;
-- 重新加载配置信息-所有配置重新加载

02 基础管理操作-修改操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 修改逻辑库名操作
[root@master conf ]# vim schema.xml
<schema name="oldboy" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
<table name="user" dataNode="sh1" />
<table name="order_t" dataNode="sh2" />
</schema>
-- 修改schema.xml文件中的逻辑库名称信息
[root@master conf ]# vim server.xml
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">oldboy</property>
<property name="defaultSchema">oldboy</property>
<!--No MyCAT Database selected 错误前会尝试使用该schema作为schema,不设置则为null,报错 -->
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">oldboy</property>
<property name="readOnly">true</property>
<property name="defaultSchema">oldboy</property>
</user>
-- 修改server.xml文件中的逻辑库名称信息,将默认TESTDB替换为oldboy
# 重新加载修改后配置文件
[root@master conf ]# mysql -uroot -p123456 -h 192.168.30.101 -P9066
mysql> reload @@config_all;
-- 所有配置重新加载
[root@master conf ]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql> show databases;
+----------+
| DATABASE |
+----------+
| oldboy   |
+----------+
1 row in set (0.00 sec)
-- 至此逻辑库名称修改完毕
# 修改逻辑库名操作(添加新的逻辑库)
[root@master conf ]# vim schema.xml
<schema name="oldboy" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
</schema>
-- 添加schema.xml文件中的逻辑库名称信息
[root@master conf ]# vim server.xml
<property name="schemas">TESTDB,oldboy</property>
-- 修改server.xml文件中的逻辑库名称信息,添加新的逻辑数据库oldboy
# 重新加载修改后配置文件
[root@master conf ]# mysql -uroot -p123456 -h 192.168.30.101 -P9066
mysql> reload @@config_all;
-- 所有配置重新加载
[root@master conf ]# mysql -uroot -p123456 -h 192.168.30.101 -P8066
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
| oldboy   |
+----------+
2 rows in set (0.00 sec)
-- 至此逻辑库名称添加完毕