MyCat简介

MyCat 引入

如今随着互联网的发展,数据的量级也是成指数式的增长,从GB到TB到PB。对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求,这个时候NoSQL的出现暂时解决了这一危机。它通过降低数据的安全性,减少对事务的支持,减少对复杂查询的支持,来获取性能上的提升。但是,在有些场合时NoSQL一些折衷是无法满足使用场景的,就比如有些使用场景是绝对要有事务与安全指标的。这个时候NoSQL肯定是无法满足的,所以还是需要使用关系性数据库。如何使用关系型数据库解决海量存储的问题呢?此时就需要做数据库集群,为了提高查询性能将一个数据库的数据分散到不同的数据库中存储,为应对此问题就出现了—MyCat 。

MyCAT的目标是:低成本的将现有的单机数据库和应用平滑迁移到”云”端,解决海量数据存储和业务规模迅速增长情况下的数据存储和访问的瓶颈问题 。

1575902332595

MyCat 历史

  1. MyCat背后是阿里曾经开源的知名产品—Cobar。Cobar的核心功能和优势是MySQL数据库分片,此产品曾经广为流传,据说最早的发起者对MySQL很精通,后来从阿里跳槽了,阿里随后开源的Cobar,并维持到 2013 年年初,然后,就没有然后了。 Cobar的思路和实现路径的确不错。基于java开发的,实现了MySQL公开的二进制传输协议,巧妙地将自己伪装成一个MySQL Server,目前市面上绝大多数MySQL客户端工具和应用都能兼容。比自己实现一个新的数据库协议要明智的多,因为生态环境在哪里摆着。

  2. MyCat是基于cobar演变而来,相对于cobar来说 , 有两个显著优势 : ①. 对cobar的代码进行了彻底的重构,MyCat在I/O方面进行了重大改进,将原来的BIO改成了NIO, 并发量有大幅提高 ; ②. 增加了对Order By、Group By、limit等聚合功能的支持,同时兼容绝大多数数据库成为通用的数据库中间件 。

  3. 简单的说,MyCat就是:一个新颖的数据库中间件产品支持MySQL集群,或者MariaDB cluster,提供高可用性数据分片集群。你可以像使用MySQL一样使用Mycat。对于开发人员来说根本感觉不到MyCat的存在。

1571824365101

MyCat 优势

MyCat是一个彻底开源的,面向企业应用数据库中间件 , 支持事务, 可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群, 在MyCat中融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server , 并结合传统数据库和新型分布式数据仓库的新一代企业级数据库中间件产品 。

优势:

1). 性能可靠稳定

基于阿里开源的Cobar产品而研发,Cobar的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得Mycat一开始就拥有一个很好的起点,站在巨人的肩膀上,能看到更远。业界优秀的开源项目和创新思路被广泛融入到Mycat的基因中,使得Mycat在很多方面都领先于目前其他一些同类的开源项目,甚至超越某些商业产品。

2). 强大的技术团队

MyCat现在由一支强大的技术团队维护 , 吸引和聚集了一大批业内大数据和云计算方面的资深工程师、架构师、DBA,优秀的团队保障了MyCat的稳定高效运行。而且MyCat不依托于任何商业公司,而且得到大批开源爱好者的支持。

3). 体系完善

MyCat已经形成了一系列的周边产品,比较有名的是 MyCat-web、MyCat-NIO、MyCat-Balance等,已经形成了一个比较完整的解决方案,而不仅仅是一个中间件。

4). 社区活跃

与MyCat数据库中间件类似的产品还有TDDL、Amoeba、Cobar 。

  1. TDDL(Taobao Distributed Data Layer)不同于其它几款产品,并非独立的中间件,只能算作中间层,是以jar包方式提供给应用调用 ,属于JDBC Shard的思想 。

  2. Amoeba是作为一个真正的独立中间件提供服务,应用去连接Amoeba操作MySQL集群,就像操作单个MySQL一样。Amoeba算中间件中的早期产品,后端还在使用JDBC Driver。

  3. Cobar是在Amoeba基础上进化的版本,一个显著变化是把后端JDBC Driver改为原生的MySQL通信协议层。

  4. MyCat又是在Cobar基础上发展的版本, 性能优良, 功能强大, 社区活跃 。

MyCat 使用场合

要想用好MyCat,就需要了解其适用场景,以下几个场景适合适用MyCat:

1). 高可用性与MySQL读写分离

高可用:利用MyCat可以轻松实现热备份,当一台服务器停机时,可以由集群中的另一台服务器自动接管业务,无需人工干预,从而保证高可用。

读写分离:通过MySQL数据库的binlog日志完成主从复制,并可以通过MyCat轻松实现读写分离,实现insert、update、delete走主库,而在select时走从库,从而缓解单台服务器的访问压力。

2). 业务数据分级存储保障

企业的数据量总是无休止的增长,这些数据的格式不一样,访问效率不一样,重要性也不一样。可以针对不同级别的数据,采用不同的存储设备,通过分级存储管理软件实现数据客体在存储设备之间自动迁移及自动访问切换。

3). 大表水平拆分,集群并行计算

数据切分是MyCat的核心功能,是指通过某种特定的条件,将存放在同一个数据库的数据,分散存储在多个数据库中,以达到分散单台设备负载的效果。当数据库量超过800万行且需要做分片时,就可以考虑使用MyCat实现数据切分。

4). 数据库路由器

MyCat基于MySQL实例的连接池复用机制,可以让每个应用最大程度共享一个MySQL实例的所有连接池,让数据库的并发访问能力大大提升。

5). 整合多种数据源

当一个项目中使用了多个数据库(Oracle,MySQL,SQL Server,PostgreSQL),并配置了多个数据源,操作起来就比较烦锁,这时就可以使用MyCat进行整合,最终我们的应用程序只需要访问一个数据源即可。

MyCat 下载

下载地址: https://github.com/MyCATApache/Mycat-download

最新下载地址: http://dl.mycat.io/

MyCat 入门

本章节主要讲解MyCat的在Linux中的安装、基本概念和基本原理,这些是学习MyCat的基础。

环境搭建

MyCat是采用java语言开发的开源的数据库中间件,支持Windows和Linux运行环境,下面介绍MyCat在Linux CentOS 6.5 中的环境搭建。

  • MySQL

  • JDK

  • MyCat

安装配置 MySQL

安装MySQL
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
A. 卸载 centos 中预安装的 mysql

rpm -qa | grep -i mysql

rpm -e mysql-libs-5.1.71-1.el6.x86_64 --nodeps

B. 上传 mysql 的安装包

alt + p -------> put E:/test/MySQL-5.6.22-1.el6.i686.rpm-bundle.tar

C. 解压 mysql 的安装包

mkdir mysql

tar -xvf MySQL-5.6.22-1.el6.i686.rpm-bundle.tar -C /root/mysql

D. 安装依赖包

yum -y install libaio.so.1 libgcc_s.so.1 libstdc++.so.6 libncurses.so.5 --setopt=protected_multilib=false

yum update libstdc++-4.4.7-4.el6.x86_64

E. 安装 mysql-client

rpm -ivh MySQL-client-5.6.22-1.el6.i686.rpm

F. 安装 mysql-server

rpm -ivh MySQL-server-5.6.22-1.el6.i686.rpm

启动停止MySQL
1
2
3
4
5
6
7
service mysql start

service mysql stop

service mysql status

service mysql restart
登录MySQL
1
2
3
4
5
6
7
8
9
10
11
12
13
mysql 安装完成之后, 会自动生成一个随机的密码, 并且保存在一个密码文件中 : /root/.mysql_secret

mysql -u root -p

登录之后, 修改密码 :

set password = password('123456');

授权远程访问 :

grant all privileges on *.* to 'root' @'%' identified by '123456';
flush privileges;

授权远程访问之后,就可以通过Navicat来连接Linux上的MySQL,但是记得关闭Linux上的防火墙(或者配置防火墙):

1573536143760

安装 JDK1.8

1
2
3
4
5
6
7
8
9
10
11
A. 上传JDK的安装包到Linux的root目录下
alt + p -----------> put D:/jdk-8u181-linux-x64.tar.gz

B. 解压压缩包 , 到 /usr/share 目录下
tar -zxvf jdk-8u181-linux-x64.tar.gz -C /usr/share/

C. 配置PATH环境变量 , 在该配置文件(/etc/profile)的最后加入如下配置
export JAVA_HOME=/usr/share/jdk1.8.0_181
export PATH=$PATH:$JAVA_HOME/bin
D. 配置生效
source /etc/profile

安装 MyCat

  1. 上传MyCat的压缩包

    1
    alt + p --------> put D:/Mycat-server-1.6.7.3-release-20190927161129-linux.tar.gz
  2. 解压MyCat的压缩包

    1
    tar -zxvf Mycat-server-1.6.7.3-release-20190927161129-linux.tar.gz -C /usr/local	
  3. MyCat的目录结构介绍

1573556739880

MyCat核心概念

分片

简单来说,就是指通过某种特定的条件,将存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。 数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。

  1. 一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切分可以称之为数据的垂直(纵向)切分。
1573622314361
  1. 另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。
1573622358104

MyCat 分片策略 :

1573659631804

虚线以上是逻辑结构图, 虚线以下是物理结构图 。

逻辑库(schema)

MyCat是一个数据库中间件,通常对实际应用来说,并不需要知道中间件的存在,业务开发人员只需要知道数据库的概念,所以数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库。

逻辑表(table)

既然有逻辑库,那么就会有逻辑表。分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可以是数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成。

  1. 分片表:是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成了完整的数据。 总而言之就是需要进行分片的表。如 :tb_order 表是一个分片表, 数据按照规则被切分到dn1、dn2两个节点。

  2. 非分片表:一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。如: tb_city是非分片表 , 数据只存于其中的一个节点 dn1 上。

  3. ER表:关系型数据库是基于实体关系模型(Entity Relationship Model)的, MyCat中的ER表便来源于此。 MyCat提出了基于ER关系的数据分片策略 , 子表的记录与其所关联的父表的记录存放在同一个数据分片中, 通过表分组(Table Group)保证数据关联查询不会跨库操作。

  4. 全局表:在一个大型的项目中,会存在一部分字典表(码表) , 在其中存储的是项目中的一些基础的数据 , 而这些基础的数据 , 数据量都不大 , 在各个业务表中可能都存在关联 。当业务表由于数据量大而分片后 , 业务表与附属的数据字典表之间的关联查询就变成了比较棘手的问题 , 在MyCat中可以通过数据冗余来解决这类表的关联查询 , 即所有分片都复制这一份数据(数据字典表),因此可以把这些冗余数据的表定义为全局表。

分片节点(dataNode)

数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点(dataNode)。

节点主机(dataHost)

数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。

分片规则(rule)

前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。

分片配置测试

需求

由于 TB_TEST 表中数据量很大, 现在需要对 TB_TEST 表进行数据分片, 分为三个数据节点 , 每一个节点主机位于不同的服务器上, 具体的结构,参考下图 :

1575724614686

环境准备

准备三台虚拟机 , 且安装好MySQL , 并配置好 :

1
2
3
4
IP 地址列表 : 
192.168.192.157
192.168.192.158
192.168.192.159

配置 schema.xml

schema.xml 作为MyCat中重要的配置文件之一,管理着MyCat的逻辑库、逻辑表以及对应的分片规则、DataNode以及DataSource。弄懂这些配置,是正确使用MyCat的前提。这里就一层层对该文件进行解析。

属性 含义
schema 标签用于定义MyCat实例中的逻辑库
table 标签定义了MyCat中的逻辑表, rule用于指定分片规则,auto-sharding-long的分片规则是按ID值的范围进行分片 1-5000000 为第1片 5000001-10000000 为第2片…. 具体设置会在后面中讲解。
dataNode 标签定义了MyCat中的数据节点,也就是通常说所的数据分片。
dataHost 标签在MyCat逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。

在服务器上创建3个数据库,命名为 db1。

修改schema.xml如下:

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
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 逻辑库配置 -->
<schema name="ITCAST" checkSQLschema="false" sqlMaxLimit="100">
<!-- 逻辑表配置 -->
<table name="TB_TEST" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
</schema>

<!-- 数据节点配置 -->
<dataNode name="dn1" dataHost="host1" database="db1" />
<dataNode name="dn2" dataHost="host2" database="db1" />
<dataNode name="dn3" dataHost="host3" database="db1" />

<!-- 节点主机配置 -->
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.192.157:3306" user="root" password="123456"></writeHost>
</dataHost>

<dataHost name="host2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.192.158:3306" user="root" password="123456"></writeHost>
</dataHost>

<dataHost name="host3" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.192.159:3306" user="root" password="123456"></writeHost>
</dataHost>

</mycat:schema>

配置 server.xml

server.xml几乎保存了所有MyCat需要的系统配置信息。最常用的是在此配置用户名、密码及权限。在system中添加UTF-8字符集设置,否则存储中文会出现问号。

1
<property name="charset">utf8</property>

修改user的设置 , 这里为 ITCAST 设置了两个用户,并且需要将原来的逻辑库的配置 , 替换为 ITCAST逻辑库 :

1
2
3
4
5
6
7
8
9
<user name="root">
<property name="password">123456</property>
<property name="schemas">ITCAST</property>
</user>

<user name="test">
<property name="password">123456</property>
<property name="schemas">ITCAST</property>
</user>

启动MyCat

启动:

1
2
3
bin/mycat start
bin/mycat stop
bin/mycat status

查看MyCat:连接端口号 8066 。

  1. 通过命令行
1
mysql -h 127.0.0.1 -P 8066 -u root -p

1573916419746

  1. 通过sqlyog连接
image-20210521134349351

MyCat分片测试

  1. 进入mycat ,执行下列语句创建一个表:
1
2
3
4
5
CREATE TABLE TB_TEST (
id BIGINT(20) NOT NULL,
title VARCHAR(100) NOT NULL ,
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8 ;
  1. 查看MySQL的3个库,发现表都自动创建好啦。好神奇。接下来是插入表数据,注意,在写 INSERT 语句时一定要写把字段列表写出来,否则会出现下列错误提示:
1
2
3
错误代码: 1064

partition table, insert must provide ColumnList

试着插入一些数据:我们会发现这些数据被写入到第一个节点中了,那什么时候数据会写到第二个节点中呢?

1
2
3
INSERT INTO TB_TEST(ID,TITLE) VALUES(1,'goods1');
INSERT INTO TB_TEST(ID,TITLE) VALUES(2,'goods2');
INSERT INTO TB_TEST(ID,TITLE) VALUES(3,'goods3');
  1. 我们插入下面的数据就可以插入第二个节点了:
1
INSERT INTO TB_TEST(ID,TITLE) VALUES(5000001,'goods5000001');

因为我们采用的分片规则是每节点存储500万条数据,所以当ID大于5000000则会存储到第二个节点上。

MyCat原理介绍

MyCat原理中最重要的一个动词就是 “拦截”, 它拦截了用户发送过来的SQL语句, 首先对SQL语句做一些特定的分析,如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL语句发往后端的真实数据库,并将返回的结果做适当处理,最终再返回给用户,如图所示。

1577358066323
  • 在图中,user表被分为三个分片节点dn1、dn2、dn3, 它们分布式在三个MySQL Server(dataHost)上,因此可以使用1-N台服务器来分片,分片规则(sharding rule)为典型的字符串枚举分片规则, 一个规则的定义是分片字段+分片函数。这里的分片字段为 status,分片函数则为字符串枚举方式。

  • MyCat收到一条SQL语句时,首先解析SQL语句涉及到的表,接着查看此表的定义,如果该表存在分片规则,则获取SQL语句里分片字段的值,并匹配分片函数,得到该SQL语句对应的分片列表,然后将SQL语句发送到相应的分片去执行,最后处理所有分片返回的数据并返回给客户端。以”select * from user where status=’0’” 为例, 查找 status=’0’ ,按照分片函数, ‘0’ 值存放在dn1,于是SQL语句被发送到第一个节点中执行, 然后再将查询的结果返回给用户。

  • 如果发送的SQL语句为 “select * from user where status in (‘0’,’1’)” , 那么SQL语句会被发送到dn1,dn2对应的主机上执行, 然后将结果集合并后输出给用户。

MyCat配置文件详解

server.xml

system 标签

属性 取值 含义
charset utf8 设置Mycat的字符集, 字符集需要与MySQL的字符集保持一致。
nonePasswordLogin 0,1 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户。
useHandshakeV10 0,1 使用该选项主要的目的是为了能够兼容高版本的jdbc驱动, 是否采用HandshakeV10Packet来与client进行通信, 1:是, 0:否。
useSqlStat 0,1 开启SQL实时统计, 1 为开启 , 0 为关闭 ;
开启之后, MyCat会自动统计SQL语句的执行情况 ;
使用:mysql -h 127.0.0.1 -P 9066 -u root -p
查看MyCat执行的SQL、执行效率比较低的SQL 、SQL的整体执行情况、读写比例等 ;
show @@sql ; show @@sql.slow ; show @@sql.sum ;
useGlobleTableCheck 0,1 是否开启全局表的一致性检测。1为开启 ,0为关闭 。
sqlExecuteTimeout 1000 SQL语句执行的超时时间 , 单位为 s ;
sequnceHandlerType 0,1,2 用来指定MyCat全局序列类型,0 为本地文件,1 为数据库方式,2 为时间戳列方式,默认使用本地文件方式,文件方式主要用于测试。
sequnceHandlerPattern 正则表达式 必须带有MYCATSEQ_或者 mycatseq_进入序列匹配流程,注意MYCATSEQ_有空格的情况。
subqueryRelationshipCheck true,false 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段,默认 false。
useCompression 0,1 开启mysql压缩协议 , 0 : 关闭, 1 : 开启。
fakeMySQLVersion 5.5,5.6 设置模拟的MySQL版本号。
defaultSqlParser 由于MyCat的最初版本使用了FoundationDB的SQL解析器,在MyCat1.3后增加了Druid解析器,所以要设置defaultSqlParser属性来指定默认的解析器;解析器有两个 : druidparser 和 fdbparser,在MyCat1.4之后,默认是druidparser,fdbparser已经废除了。
processors 1,2…. 指定系统可用的线程数量, 默认值为CPU核心 x 每个核心运行线程数量; processors 会影响processorBufferPool, processorBufferLocalPercent, processorExecutor属性, 所有, 在性能调优时, 可以适当地修改processors值。
processorBufferChunk 指定每次分配Socket Direct Buffer默认值为4096字节, 也会影响BufferPool长度, 如果一次性获取字节过多而导致buffer不够用, 则会出现警告, 可以调大该值。
processorExecutor 指定NIOProcessor上共享 businessExecutor固定线程池的大小; MyCat把异步任务交给 businessExecutor线程池中, 在新版本的MyCat中这个连接池使用频次不高, 可以适当地把该值调小。
packetHeaderSize 指定MySQL协议中的报文头长度, 默认4个字节。
maxPacketSize 指定MySQL协议可以携带的数据最大大小, 默认值为16M。
idleTimeout 30 指定连接的空闲时间的超时长度;如果超时,将关闭资源并回收, 默认30分钟
txIsolation 1,2,3,4 初始化前端连接的事务隔离级别,默认为 REPEATED_READ , 对应数字为3
READ_UNCOMMITED=1;
READ_COMMITTED=2;
REPEATED_READ=3;
SERIALIZABLE=4;
sqlExecuteTimeout 300 执行SQL的超时时间, 如果SQL语句执行超时,将关闭连接; 默认300秒。
serverPort 8066 定义MyCat的使用端口, 默认8066。
managerPort 9066 定义MyCat的管理端口, 默认9066。

user 标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">ITCAST</property>
<property name="readOnly">true</property>
<property name="benchmark">1000</property>
<property name="usingDecrypt">0</property>

<!-- 表级 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标签主要用于定义登录MyCat的用户和权限 :

  1. <user name=”root” defaultAccount=”true”> : name 属性用于声明用户名 。

  2. <property name=”password”>123456</property> : 指定该用户名访问MyCat的密码 。

  3. <property name=”schemas”>ITCAST</property> : 能够访问的逻辑库, 多个的话, 使用 “,” 分割。

  4. <property name=”readOnly”>true</property> : 是否只读。

  5. <property name=”benchmark”>11111</property> : 指定前端的整体连接数量 , 0 或不设置表示不限制 。

  6. <property name=”usingDecrypt”>0</property> : 是否对密码加密默认 0 否 , 1 是。设置密码加密后需要使用如下命令获取加密后的密码,并修改配置文件的密码为加密后的密码,登录时照样使用”123456”进行登录。

1
java -cp Mycat-server-1.6.7.3-release.jar io.mycat.util.DecryptUtil 0:root:123456
  1. <privileges check=”false”>
  • 对用户的 schema 及下级的 table 进行精细化的 DML 权限控制;

  • privileges 节点中的 check 属性是用于标识是否开启 DML 权限检查, 默认 false 标识不检查,当然 privileges 节点不配置,等同 check=false, 由于 Mycat 一个用户的 schemas 属性可配置多个 schema ,所以 privileges 的下级节点 schema 节点同样 可配置多个,对多库多表进行细粒度的 DML 权限控制;

  • 权限修饰符四位数字(0000 - 1111),对应的操作是 IUSD ( 增,改,查,删 )。同时配置了库跟表的权限,就近原则。以表权限为准。

firewall 标签

firewall标签用来定义防火墙;firewall下whitehost标签用来定义 IP白名单 ,blacklist用来定义 SQL黑名单。

1
2
3
4
5
6
7
8
9
10
<firewall>
<!-- 白名单配置 -->
<whitehost>
<host user="root" host="127.0.0.1"></host>
</whitehost>
<!-- 黑名单配置 -->
<blacklist check="true">
<property name="selelctAllow">false</property>
</blacklist>
</firewall>

黑名单拦截明细配置:

配置项 缺省值 描述
selelctAllow true 是否允许执行 SELECT 语句。
selectAllColumnAllow true 是否允许执行 SELECT * FROM T 这样的语句。如果设置为 false,不允许执行 select * from t,但可以select * from (select id, name from t) a。这个选项是防御程序通过调用 select * 获得数据表的结构信息。
selectIntoAllow true SELECT 查询中是否允许 INTO 字句。
deleteAllow true 是否允许执行 DELETE 语句。
updateAllow true 是否允许执行 UPDATE 语句。
insertAllow true 是否允许执行 INSERT 语句。
replaceAllow true 是否允许执行 REPLACE 语句。
mergeAllow true 是否允许执行 MERGE 语句,这个只在 Oracle 中有用。
callAllow true 是否允许通过 jdbc 的 call 语法调用存储过程。
setAllow true 是否允许使用 SET 语法。
truncateAllow true truncate 语句是危险,缺省打开,若需要自行关闭。
createTableAllow true 是否允许创建表。
alterTableAllow true 是否允许执行 Alter Table 语句。
dropTableAllow true 是否允许修改表。
commentAllow false 是否允许语句中存在注释,Oracle 的用户不用担心,Wall 能够识别 hints和注释的区别。
noneBaseStatementAllow false 是否允许非以上基本语句的其他语句,缺省关闭,通过这个选项就能够屏蔽 DDL。
multiStatementAllow false 是否允许一次执行多条语句,缺省关闭。
useAllow true 是否允许执行 mysql 的 use 语句,缺省打开。
describeAllow true 是否允许执行 mysql 的 describe 语句,缺省打开。
showAllow true 是否允许执行 mysql 的 show 语句,缺省打开。
commitAllow true 是否允许执行 commit 操作。
rollbackAllow true 是否允许执行 roll back 操作。
拦截配置-永真条件
selectWhereAlwayTrueCheck true 检查 SELECT 语句的 WHERE 子句是否是一个永真条件。
selectHavingAlwayTrueCheck true 检查 SELECT 语句的 HAVING 子句是否是一个永真条件。
deleteWhereAlwayTrueCheck true 检查 DELETE 语句的 WHERE 子句是否是一个永真条件。
deleteWhereNoneCheck false 检查 DELETE 语句是否无 where 条件,这是有风险的,但不是 SQL 注入类型的风险。
updateWhereAlayTrueCheck true 检查 UPDATE 语句的 WHERE 子句是否是一个永真条件。
updateWhereNoneCheck false 检查 UPDATE 语句是否无 where 条件,这是有风险的,但不是SQL 注入类型的风险。
conditionAndAlwayTrueAllow false 检查查询条件(WHERE/HAVING 子句)中是否包含 AND 永真条件。
conditionAndAlwayFalseAllow false 检查查询条件(WHERE/HAVING 子句)中是否包含 AND 永假条件。
conditionLikeTrueAllow true 检查查询条件(WHERE/HAVING 子句)中是否包含 LIKE 永真条件。
其他拦截配置
selectIntoOutfileAllow false SELECT … INTO OUTFILE 是否允许,这个是 mysql 注入攻击的常见手段,缺省是禁止的。
selectUnionCheck true 检测 SELECT UNION。
selectMinusCheck true 检测 SELECT MINUS。
selectExceptCheck true 检测 SELECT EXCEPT。
selectIntersectCheck true 检测 SELECT INTERSECT。
mustParameterized false 是否必须参数化,如果为 True,则不允许类似 WHERE ID = 1 这种不参数化的 SQL。
strictSyntaxCheck true 是否进行严格的语法检测,Druid SQL Parser 在某些场景不能覆盖所有的SQL 语法,出现解析 SQL 出错,可以临时把这个选项设置为 false,同时把 SQL 反馈给 Druid 的开发者。
conditionOpXorAllow false 查询条件中是否允许有 XOR 条件。XOR 不常用,很难判断永真或者永假,缺省不允许。
conditionOpBitwseAllow true 查询条件中是否允许有”&”、”~”、”|”、”^”运算符。
conditionDoubleConstAllow false 查询条件中是否允许连续两个常量运算表达式。
minusAllow true 是否允许 SELECT * FROM A MINUS SELECT * FROM B 这样的语句。
intersectAllow true 是否允许 SELECT * FROM A INTERSECT SELECT * FROM B 这样的语句。
constArithmeticAllow true 拦截常量运算的条件,比如说 WHERE FID = 3 - 1,其中”3 - 1”是常量运算表达式。
limitZeroAllow false 是否允许 limit 0 这样的语句。
禁用对象检测配置
tableCheck true 检测是否使用了禁用的表。
schemaCheck true 检测是否使用了禁用的 Schema。
functionCheck true 检测是否使用了禁用的函数。
objectCheck true 检测是否使用了“禁用对对象”。
variantCheck true 检测是否使用了“禁用的变量”。
readOnlyTables 指定的表只读,不能够在 SELECT INTO、DELETE、UPDATE、INSERT、MERGE 中作为”被修改表”出现。

schema.xml

schema.xml 作为MyCat中最重要的配置文件之一 , 涵盖了MyCat的逻辑库 、 表 、 分片规则、分片节点及数据源的配置。

schema 标签

1
2
3
<schema name="ITCAST" checkSQLschema="false" sqlMaxLimit="100">
<table name="TB_TEST" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
</schema>

schema 标签用于定义 MyCat实例中的逻辑库 , 一个MyCat实例中, 可以有多个逻辑库 , 可以通过 schema 标签来划分不同的逻辑库。MyCat中的逻辑库的概念 , 等同于MySQL中的database概念 , 需要操作某个逻辑库下的表时, 也需要切换逻辑库:

1
use ITCAST;
属性

schema 标签的属性如下 :

  1. name:指定逻辑库的库名 , 可以自己定义任何字符串 。

  2. checkSQLschema:取值为 true / false ;当设置为true时,如果执行的语句为 “select * from ITCAST.TB_TEST;” ,则MyCat会自动把schema字符去掉,把SQL语句修改为 “select * from TB_TEST;” ,可以避免SQL发送到后端数据库执行时,报table不存在的异常 。不过当我们在编写SQL语句时,指定了一个不存在schema, MyCat是不会帮我们自动去除的,这个时候数据库就会报错,所以在编写SQL语句时,最好不要加逻辑库的库名,直接查询表即可。

  3. sqlMaxLimit:当该属性设置为某个数值时,每次执行的SQL语句如果没有加上limit语句,MyCat也会自动在limit语句后面加上对应的数值 。也就是说,如果设置了该值为100,则执行 “select * from TB_TEST 与 select * from TB_TEST limit 100;” 是相同的效果 。所以在正常的使用中, 建立设置该值 , 这样就可以避免每次有过多的数据返回。

子标签table

table 标签定义了MyCat中逻辑库schema下的逻辑表 , 所有需要拆分的表都需要在table标签中定义 。

1
<table name="TB_TEST" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

属性如下 :

1574954845578
  1. name :定义逻辑表的表名,在该逻辑库下必须唯一。

  2. dataNode:定义的逻辑表所属的dataNode,该属性需要与dataNode标签中的name属性的值对应。 如果一张表拆分的数据,存储在多个数据节点上,多个节点的名称使用”,”分隔 。

1574955059453

  1. rule:该属性用于指定逻辑表的分片规则的名字,规则的名字是在rule.xml文件中定义的,必须与tableRule标签中name属性对应。

1574955534319

  1. ruleRequired:该属性用于指定表是否绑定分片规则,如果配置为true, 但是没有具体的rule, 程序会报错。

  2. primaryKey:逻辑表对应真实表的主键,如: 分片规则是使用主键进行分片,使用主键进行查询时,就会发送查询语句到配置的所有的datanode上;如果使用该属性配置真实表的主键,那么MyCat会缓存主键与具体datanode的信息,再次使用主键查询就不会进行广播式查询了,而是直接将SQL发送给具体的datanode。

  3. type:该属性定义了逻辑表的类型,目前逻辑表只有全局表和普通表。全局表:type的值是 global,代表 全局表 。普通表:无。

  4. autoIncrement:mysql对非自增长主键,使用last_insert_id() 是不会返回结果的,只会返回0。所以只有定义了自增长主键的表,才可以用last_insert_id()返回主键值。MyCat提供了自增长主键功能,但是对应的mysql节点上数据表,没有auto_increment,那么在MyCat层调用last_insert_id()也是不会返回结果的。如果使用这个功能, 则最好配合数据库模式的全局序列。使用 autoIncrement=”true” 指定该表使用自增长主键,这样MyCat才不会抛出 “分片键找不到” 的异常。 autoIncrement的默认值为 false。

  5. needAddLimit:指定表是否需要自动在每个语句的后面加上limit限制, 默认为true。

dataNode 标签

1
<dataNode name="dn1" dataHost="host1" database="db1" />

dataNode标签中定义了MyCat中的数据节点,也就是通常说的数据分片。一个dataNode标签就是一个独立的数据分片。具体的属性如下 :

属性 含义 描述
name 数据节点的名称 需要唯一 ; 在table标签中会引用这个名字,标识表与分片的对应关系。
dataHost 数据库实例主机名称 引用自 dataHost 标签中name属性。
database 定义分片所属的数据库

dataHost 标签

1
2
3
4
5
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.192.157:3306" user="root" password="123456"></writeHost>
</dataHost>

该标签在MyCat逻辑库中作为底层标签存在,直接定义了具体的数据库实例、读写分离、心跳语句。

属性
属性 含义 描述
name 数据节点名称 唯一标识, 供上层标签使用。
maxCon 最大连接数 内部的writeHost、readHost都会使用这个属性。
minCon 最小连接数 内部的writeHost、readHost初始化连接池的大小。
balance 负载均衡类型 取值0,1,2,3 ; 后面章节会详细介绍;
writeType 写操作分发方式 0 : 写操作都转发到第1台writeHost, writeHost1挂了,会切换到writeHost2上;
1 : 所有的写操作都随机地发送到配置的writeHost上 。
dbType 后端数据库类型 mysql, mongodb , oracle
dbDriver 数据库驱动 指定连接后端数据库的驱动,目前可选值有 native和JDBC。native执行的是二进制的MySQL协议,可以使用MySQL和MariaDB。其他类型数据库需要使用JDBC(需要在MyCat/lib目录下加入驱动jar)。
switchType 数据库切换策略 取值 -1,1,2,3 ; 后面章节会详细介绍;
子标签heartbeat

配置MyCat与后端数据库的心跳,用于检测后端数据库的状态。heartbeat用于配置心跳检查语句。例如 : MySQL中可以使用 select user(), Oracle中可以使用 select 1 from dual等。

子标签 writeHost、readHost

指定后端数据库的相关配置, 用于实例化后端连接池。 writeHost指定写实例, readHost指定读实例。在一个dataHost中可以定义多个writeHost和readHost。但是,如果writeHost指定的后端数据库宕机, 那么这个writeHost绑定的所有readHost也将不可用。

属性:

属性名 含义 取值
host 实例主机标识 对于writeHost一般使用 *M1;对于readHost,一般使用 *S1;
url 后端数据库连接地址 如果是native,一般为 ip:port ; 如果是JDBC, 一般为jdbc:mysql://ip:port/
user 数据库用户名 root
password 数据库密码 itcast
weight 权重 在readHost中作为读节点权重
usingDecrypt 密码加密 默认 0 否 , 1 是

rule.xml

rule.xml中定义所有拆分表的规则,在使用过程中可以灵活的使用分片算法,或者对同一个分片算法使用不同的参数,它让分片过程可配置化。

tableRule标签

1
2
3
4
5
6
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
  1. name : 指定分片算法的名称。

  2. rule : 定义分片算法的具体内容 。

  3. columns : 指定对应的表中用于分片的列名。

  4. algorithm : 对应function中指定的算法名称。

Function标签

1
2
3
<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
</function>
  1. name : 指定算法名称, 该文件中唯一 。

  2. class : 指定算法的具体类。

  3. property : 根据算法的要求执行 。

sequence 配置文件

在分库分表的情况下,原有的自增主键已无法满足在集群中全局唯一的主键,因此,MyCat中提供了全局sequence来实现主键,并保证全局唯一。那么在MyCat的配置文件 sequence_conf.properties 中就配置的是序列的相关配置。

主要包含以下几种形式:

  1. 本地文件方式

  2. 数据库方式

  3. 本地时间戳方式

  4. 其他方式

  5. 自增长主键