中间件mycat

  • 一、mycat基础概念
  • 二、部署主从复制
  • 三、mycat安装部署
  • 四、mycat读写分离的实现
  • 五、垂直拆分——分库
  • 六、水平拆分——分表
  • 七、mycat的高可用方案


一、mycat基础概念

1.mycat简介

(1)彻底开源,面向企业应用开发的大数据库集群;

(2)支持事务、ACID、可以替代MySQL的加强版数据库;

(3)可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群;

(4)融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server;

(5)结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品;

(6)新颖的数据库中间件产品;

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

(1)读写分离;

(2)数据分片垂直拆分(分库)、水平拆分(分表)、垂直+水平拆分(分库分表);

(3)多数据源整合;

3.数据库中间件对比

(1)Cobar属于阿里B2B事业群,始于2008年,在阿里服役3年多,接管3000+个MySQL数据库的schema,集群日处理在线SQL请求50亿次以上。由于Cobar发起人的离职,Cobar停止维护。

(2)Mycat是开源社区在阿里cobar基础上进行二次开发,解决了cobar存在的问题,并且加入了许多新的功能。

(3)OneProxy基于MySQL官方的proxy思想,利用c进行开发,是一款商业收费的中间件。舍弃了一些功能,专注在性能和稳定性上。

(4)kingshard由小团队用go语言开发,还需要发展,需要不断完善。

(5)Vitess是Youtube生产在使用,架构很复杂。不支持MySQL原生协议,使用时需要大量改造成本。

(6)Atlas是360团队基于mysql proxy改写,功能还需完善,高并发下不稳定。

(7)MaxScale是mariadb(MySQL原作者维护的一个版本)研发的中间件。

(8)MySQLRoute是MySQL官方Oracle公司发布的中间件。

4.支持的数据库
mycat支持MySQL、ORACLE、SQLServer等一些主流的数据库。
5.核心技术(分库分表)
数据库分片:指通过某种特定的条件,将存放在一个数据库中的数据分散存放在不同的多个数据库(主机)中,达到分散单台设备负载的目的。
根据切片规则,可分为以下两种切片模式。
MyCAT通过定义表的分片规则来实现分片,每个表格可以捆绑一个分片规则,每个分片规则指定一个分片字段并绑定一个函数,来实现动态分片算法。

(1)Schema:逻辑库,与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的Table。

(2)Table:逻辑表,即物理数据库中存储的某一张表,与传统数据库不同,这里的表格需要声明其所存储的逻辑数据节点DataNode。在此可以指定表的分片规则。

(3)DataNode:MyCAT的逻辑数据节点,是存放table的具体物理节点,也称之为分片节点,通过DataSource来关联到后端某个具体数据库上。

(4)DataSource:定义某个物理库的访问地址,用于捆绑到DataNode上。

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

二、部署主从复制

1.master开启二进制日志

[root@master ~]# vim /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
pid-file=/usr/local/mysql/data/mysqld.pid
log-error=/usr/local/mysql/data/mysqld.err
socket=/tmp/mysql.sock
log-bin=mysql-bin
server-id=1
[root@master ~]# systemctl start mysqld

2.查看master状态信息

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

3.master上创建同步用户(需要Replication slave权限)

mysql> grant Replication slave on *.* to rep@'192.168.229.%' identified by 'Test123!';
Query OK, 0 rows affected, 1 warning (0.01 sec)

4.slave上操作开启relay_log(默认开启,可以写入配置文件)

[root@slave ~]# vim /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
pid-file=/usr/local/mysql/data/mysqld.pid
log-error=/usr/local/mysql/data/mysqld.err
socket=/tmp/mysql.sock
relay_log=slave-relay-bin
relay_log_index=slave-relay-bin.index
server_id=2
[root@slave ~]# service mysqld restart
Shutting down MySQL.. SUCCESS! 
Starting MySQL.. SUCCESS!

5.slave上绑定master并开启slave

mysql> change master to master_host='192.168.229.215',
    -> master_user='rep',
    -> master_password='Test123!',
    -> master_port=3306,
    -> master_log_file='mysql-bin.000001',
    -> master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.229.215
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 448
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 614
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 448
              Relay_Log_Space: 815
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 47a57d36-2a54-11eb-a6fc-000c29b43d44
             Master_Info_File: /usr/local/mysql/data/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

6.验证主从复制
(1)master上创建库和表

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> use test;
Database changed
mysql> create table mytest (id int primary key auto_increment,name varchar(20));
Query OK, 0 rows affected (0.00 sec)

mysql> insert into mytest(name) values("zhangsan"),("lisi");
Query OK, 2 rows affected (0.06 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from mytest;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
+----+----------+
2 rows in set (0.00 sec)

(2)slave上查看是否成功同步

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.01 sec)

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| mytest         |
+----------------+
1 row in set (0.00 sec)

mysql> select * from mytest;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
+----+----------+
2 rows in set (0.00 sec)

三、mycat安装部署

mycat官网1.前提环境

(1)jdk:jdk必须是1.8及以上版本

(2)Mysql:mysql5.7

2.下载安装mycat

[root@mycat ~]# yum -y install java-devel
[root@mycat ~]# cd /usr/local/src/
[root@mycat src]# wget http://dl.mycat.org.cn/1.6.7.6/20201126013625/Mycat-server-1.6.7.6-release-20201126013625-linux.tar.gz
[root@mycat src]# tar zxf Mycat-server-1.6.7.6-release-20201126013625-linux.tar.gz
[root@mycat src]# cd mycat/
[root@mycat mycat]# ls
bin  catlet  conf  lib  logs  version.txt
[root@mycat mycat]# ln -s /usr/local/src/mycat/bin/* /usr/local/bin/  #都需要完整路径

3.mycat的用法
Mycat的默认端口号:8066

[root@mycat mycat]# mycat --help
Usage: /usr/local/bin/mycat { console | start | stop | restart | status | dump }

4.master上创建用户允许远程登录

mysql> grant all on *.* to root@'%' identified by "Test123!";
Query OK, 0 rows affected, 1 warning (0.00 sec)

5.配置文件的相关配置

schema.xml:定义逻辑库、表、分片节点等内容;

rule.xml:定义分片规则;

server.xml:定义用户以及系统相关变量,如端口等;

6.修改配置文件server.xml
修改用户信息,与mysql的root用户进行区分。

[root@mycat mycat]# ls
bin  catlet  conf  lib  logs  version.txt
[root@mycat mycat]# vim conf/server.xml
#把root改为mycat,不改也可以,只是为了区分。
        <user name="mycat" defaultAccount="true">
                <property name="password">123456</property>
                <property name="schemas">TESTDB</property>
                <property name="defaultSchema">TESTDB</property>
        </user>

7.修改配置文件schema.xml

[root@mycat mycat]# vim conf/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="dn1">
#randomDataNode改成dataNode,checkSQLschema改为false。
        </schema>

        <dataNode name="dn1" dataHost="host1" database="test" />
#name和上面的一样,host改为host1,database改为master中的同步库。

        <dataHost name="host1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
#datahost name和上面一样,dbDriver改成native。

                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.229.215:3306" user="root"
                                   password="Test123!">
#密码为远程登录用户的密码
                </writeHost>
        </dataHost>
</mycat:schema>

8.把master上的mysql发到mycat主机上

[root@master ~]# scp /usr/local/mysql/bin/mysql root@192.168.229.221:/usr/local/bin/

9.启动mycat

[root@mycat-5 ~]# mycat console  #启动到当前界面
或者
[root@mycat-5 ~]# mycat start  #启动到后台

10.测试连接

[root@mycat mycat]# mysql -umycat -p123456 -h 192.168.229.221 -P 8066
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 2
Server version: 5.6.29-mycat-1.6.7.6-release-20201126013625 MyCat Server (OpenCloudDB)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
+----------+
1 row in set (0.00 sec)

mysql> use TESTDB
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| mytest         |
+----------------+
1 row in set (0.01 sec)

mysql> select * from mytest;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    2 | lisi     |
+------+----------+
2 rows in set (0.01 sec)

四、mycat读写分离的实现

1.修改配置文件schema.xml
mycat读写分离是建立在Mysq主从复制的基础上的,修改配置文件schema.xml。

[root@mycat mycat]# vim conf/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="dn1">

        </schema>
        <dataNode name="dn1" dataHost="host1" database="test" />
        <dataHost name="host1" maxCon="1000" minCon="10" balance="2"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.229.215:3306" user="root"
                                   password="Test123!">
                <readHost host="hostS2" url="192.168.229.220:3306" user="root" password="Test123!" />  #添加一行内容密码为远程登录用户的密码
                </writeHost>
        </dataHost>
</mycat:schema>

设置balance="1"与writeType=“0”
(1)Balance参数设置
修改balance的属性,通过此属性配置读写分离的类型为负载均衡类型,取值有4种

(1)balance="0"
不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。

(2)balance="1"
全部readHost与stand by writeHost参与select语句的负载均衡。
也就是当双主双从模式(M1->S1,M2->S2,并且M1与M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。

(3)balance="2"
所有读操作都随机在writeHost、readhost上分发。

(4)balance="3",所有读请求随机分发到readhost执行,writerHost不负担读压力。

(2)WriteType参数设置

(1)writeType=“0”
所有写操作都发送到可用的writeHost上。

(2)writeType=“1”
所有写操作都随机的发送到readHost。

(3)writeType=“2”
所有写操作都随机分发到writeHost、readhost上。

“readHost是从属于writeHost的,即它从哪个writeHost获取同步数据。因此,当它所属的writeHost宕机了,则它也不会再参与到读写分离中来。这是因为此时,它的数据已经“不可靠”了。基于这个考虑,目前mycat 1.3和1.4版本中,若想支持MySQL一主一从的标准配置,并且在主节点宕机的情况下,从节点还能读取数据,则需要在Mycat里配置为两个writeHost并设置banlance=1。”
设置switchType=“2” 与slaveThreshold=“100”
(3)switchType目前有三种选择

-1:表示不自动切换;

1:默认值,自动切换;

2:基于MySQL主从同步的状态决定是否切换;

“Mycat心跳检查语句配置为show slave status,dataHost上定义两个新属性:switchType=“2"与slaveThreshold=“100”,此时意味着开启MySQL主从复制状态绑定的读写分离与切换机制。Mycat心跳机制通过检测show slave status中的"Seconds_Behind_Master”,“Slave_IO_Running”,"Slave_SQL_Running"三个字段来确定当前主从同步的状态以及Seconds_Behind_Master主从复制时延。”
2.启动程序

[root@mycat conf]# mycat console

3.验证读写分离
(1)修改master的配置文件

[root@master ~]# vim /etc/my.cnf
添加如下内容
binlog_format=statement
[root@master ~]# systemctl restart mysqld

(2)在写主机master插入数据

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into mytest(name) values(@@hostname);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from mytest;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
|  3 | master   |
+----+----------+
3 rows in set (0.00 sec)
#主从主机数据不一致了;

(3)读主机slave上查看数据

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from mytest;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
|  3 | slave    |
+----+----------+
3 rows in set (0.01 sec)

(4)在mycat里查询验证

[root@mycat ~]# mysql -umycat -p123456 -h 192.168.229.187 -P 8066
mysql> use TESTDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from mytest;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    2 | lisi     |
|    3 | slave    |
+------+----------+
3 rows in set (0.01 sec)
五、垂直拆分——分库

一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如何划分表分库的原则:有紧密关联关系的表应该在一个库里,相互没有关联关系的表可以分到不同的库里。

#客户表 rows:20万
create table customer(
id int auto_increment,
name varchar(200),
primary key(id)
);

#订单表 rows:600万
create table orders(
id int auto_increment,
order_type int,
customer_id int,
amount decimal(10,2),
primary key(id)
);

#订单详细表 rows:600万
create table orders_detail(
id int auto_increment,
detail varchar(2000),
order_id int,
primary key(id)
);

#订单状态字典表 rows:20万
create table dict_order_type(
id int auto_increment,
order_type varchar(200),
primary key(id)
);

以上四个表如何分库?
客户表分在一个数据库,另外三张都需要关联查询,分在另外一个数据库。
实现分库
1.修改schema.xml配置文件

[root@mycat 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="dn1">
        <table name="customer" dataNode="dn2"></table>
        </schema>
        <dataNode name="dn1" dataHost="host1" database="test" />
        <dataNode name="dn2" dataHost="host2" database="test" />
        <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.229.215:3306" user="root"
                                   password="Test123!">
                <readHost host="hostS2" url="192.168.229.220:3306" user="root" password="Test123!" />
                </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="hostM2" url="192.168.229.211:3306" user="root"
                                   password="Test123!">
                </writeHost>
        </dataHost>
</mycat:schema>

2.新增主机master2

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> grant all on *.* to root@'%' identified by 'Test123!';
Query OK, 0 rows affected, 1 warning (0.01 sec)

3.新增两个空白库
分库操作不是在原来的老数据库上进行操作,需要准备两台机器分别安装新的数据库。

#在数据节点dn1、dn2上分别创建数据库orders
mysql> create database orders;
Query OK, 1 row affected (0.00 sec)

4.访问mycat进行分库

[root@mycat conf]# mycat console

#另开一个mycat终端
[root@mycat ~]# mysql -umycat -p123456 -h 192.168.229.187 -P 8066

mysql> use TESTDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
#创建4张表
create table customer(
id int auto_increment,
name varchar(200),
primary key(id)
);

create table orders(
id int auto_increment,
order_type int,
customer_id int,
amount decimal(10,2),
primary key(id)
);

create table orders_detail(
id int auto_increment,
detail varchar(2000),
order_id int,
primary key(id)
);

create table dict_order_type(
id int auto_increment,
order_type varchar(200),
primary key(id)
);

5.验证分库成功
(1)master1上查看表

mysql> use test;
Database changed
mysql> show tables;
+-----------------+
| Tables_in_test  |
+-----------------+
| dict_order_type |
| mytest          |
| orders          |
| orders_detail   |
+-----------------+
4 rows in set (0.00 sec)

(2)master2上查看表

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| CUSTOMER       |
+----------------+
1 row in set (0.00 sec)
六、水平拆分——分表

相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库中,每个表中包含一部分数据。简单来说,可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。
实现分表
选择要拆分的表,MySQL单表存储数据条数是有瓶颈的,单表达到1000万条数据就达到了瓶颈,会影响查询效率,需要进行水平拆分(分表)进行优化。
例如:例子中的orders、orders_detail都已经达到600万行数据,需要进行分表优化。
分表字段以orders表为例,可以根据不同自字段进行分表。

编号

分表字段

效果

1

id(主键、或创建时间)

查询订单注重时效,历史订单被查询的次数少,如此分片会造成一个节点访问多,一个访问少,不平均。

2

customer_id(客户id)

根据客户id去分,两个节点访问平均,一个客户的所有订单都在同一个节点

1.修改配置文件schema.xml

[root@mycat 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="dn1">
        <table name="customer" dataNode="dn2"></table>
        <table name="orders" dataNode="dn1,dn2" rule="mod_rule">
                <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
        </table>
        </schema>
        <dataNode name="dn1" dataHost="host1" database="test" />
        <dataNode name="dn2" dataHost="host2" database="test" />
        <dataHost name="host1" maxCon="1000" minCon="10" balance="1"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM1" url="192.168.229.215:3306" user="root"
                                   password="Test123!">
                <readHost host="hostS2" url="192.168.229.220:3306" user="root" password="Test123!" />
                </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="hostM2" url="192.168.229.211:3306" user="root"
                                   password="Test123!">
                </writeHost>
        </dataHost>
</mycat:schema>

为orders表设置数据节点为dn1、dn2,并指定分片规则为mod_rule(自定义的名字)。

<table name="orders" dataNode="dn1,dn2" rule="mod_rule">

2.修改配置文件rule.xml

#在rule配置文件里新增分片规则mod_rule,并指定规则适用字段为customer_id。
#还有选择分片算法mod-long(对字段求模运算),customer_id对两个节点求模,根据结果分片。
#配置算法mod-long参数count为2,两个节点。
[root@mycat conf]# vim rule.xml
...
        </tableRule>
        <tableRule name="mod_rule">
                <rule>
                        <columns>customer_id</columns>
                        <algorithm>mod-long</algorithm>
                </rule>
        </tableRule>
...
        </function>
        <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
                <!-- how many data nodes -->
                <property name="count">2</property>
        </function>
...

3.在数据节点master2/dn2上建orders表

create table orders(
id int auto_increment,
order_type int,
customer_id int,
amount decimal(10,2),
primary key(id)
);

4.重启mycat,让配置生效

[root@mycat conf]# mycat console

5.访问mycat实现分片

#在mycat里向orders表插入数据,INSERT字段不能省略;
mysql> use TESTDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------+
| Tables_in_test  |
+-----------------+
| customer        |
| orders          |
| orders_detail   |
| dict_order_type |
| mytest          |
+-----------------+
5 rows in set (0.00 sec)

insert into orders(id,order_type,customer_id,amount) VALUES(1,101,100,100100);
insert into orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);
insert into orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);
insert into orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);
insert into orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);
insert into orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);

6.mycat查看orders数据

mysql> select * from orders;
+------+------------+-------------+-----------+
| id   | order_type | customer_id | amount    |
+------+------------+-------------+-----------+
|    1 |        101 |         100 | 100100.00 |
|    2 |        101 |         100 | 100300.00 |
|    6 |        102 |         100 | 100020.00 |
|    3 |        101 |         101 | 120000.00 |
|    4 |        101 |         101 | 103000.00 |
|    5 |        102 |         101 | 100400.00 |
+------+------------+-------------+-----------+
6 rows in set (0.00 sec)

7.dn1/master1查看orders数据

mysql> select * from orders;
+----+------------+-------------+-----------+
| id | order_type | customer_id | amount    |
+----+------------+-------------+-----------+
|  1 |        101 |         100 | 100100.00 |
|  2 |        101 |         100 | 100300.00 |
|  6 |        102 |         100 | 100020.00 |
+----+------------+-------------+-----------+
3 rows in set (0.00 sec)

8.dn2/master2查看orders表数据

mysql> select * from orders;
+----+------------+-------------+-----------+
| id | order_type | customer_id | amount    |
+----+------------+-------------+-----------+
|  3 |        101 |         101 | 120000.00 |
|  4 |        101 |         101 | 103000.00 |
|  5 |        102 |         101 | 100400.00 |
+----+------------+-------------+-----------+
3 rows in set (0.00 sec)

9.如果需要内连接或者外连接查询,则需在配置文件中添加如下内容。

<table name="orders" dataNode="dn1,dn2" rule="mod_rule">
                <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
        </table>

10.在dn2/master2上创建orders_detail表

create table orders_detail(
id int auto_increment,
detail varchar(2000),
order_id int,
primary key(id)
);

11.重启mycat访问mycat向orders_detail表插入数据
注意:schema.xml文件中的dbDriver设置为native才可以,jdbc则会插入失败。

[root@mycat conf]# mycat console
[root@mycat ~]# mysql -umycat -p123456 -h 192.168.229.187 -P 8066

insert into orders_detail(id,detail,order_id) values (1,'detail',1);
insert into orders_detail(id,detail,order_id) values (2,'detail',2);
insert into orders_detail(id,detail,order_id) values (3,'detail',3);
insert into orders_detail(id,detail,order_id) values (4,'detail',4);
insert into orders_detail(id,detail,order_id) values (5,'detail',5);
insert into orders_detail(id,detail,order_id) values (6,'detail',6);

mysql> select orders.*,orders_detail.detail from orders inner join orders_detail on orders.id=orders_detail.order_id;
+----+------------+-------------+-----------+--------+
| id | order_type | customer_id | amount    | detail |
+----+------------+-------------+-----------+--------+
|  3 |        101 |         101 | 120000.00 | detail |
|  4 |        101 |         101 | 103000.00 | detail |
|  5 |        102 |         101 | 100400.00 | detail |
|  1 |        101 |         100 | 100100.00 | detail |
|  2 |        101 |         100 | 100300.00 | detail |
|  6 |        102 |         100 | 100020.00 | detail |
+----+------------+-------------+-----------+--------+
6 rows in set (0.03 sec)

12.全局表
在分片的情况下,当业务表因为规模而进行分片后,业务表与这些附属的字典表之间的关联,就成了比较棘手的问题,考虑到字典表具有以下几个特性:

(1)变动不频繁;

(2)数据量总体变化不大;

(3)数据规模不大,很少有超过数十万条记录;

鉴于此,mycat定义了一种特殊的表,称之为“全局表”,全局表具有以下特性:

(1)全局表的插入、更新操作会实时在所有节点上执行,保持各个分片的数据一致性;

(2)全局表的查询操作,只从一个节点获取;

(3)全局表可以跟任何一个表进行join操作将字典表或者符合字典表特性的一些表定义为全局表,则从另外一个方面,很好的解决了数据join的难题。

通过全局表+基于E-R关系的分片策略,mycat可以满足80%以上的企业应用开发。
(1)修改schema.xml配置文件

[root@mycat 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="dn1">
        <table name="customer" dataNode="dn2"></table>
        <table name="orders" dataNode="dn1,dn2" rule="mod_rule">
                <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
        </table>
        <table name="dict_order_type" dataNode="dn1,dn2" type="global">
        </table>
        </schema>
        <dataNode name="dn1" dataHost="host1" database="test" />
        <dataNode name="dn2" dataHost="host2" database="test" />
        <dataHost name="host1" maxCon="1000" minCon="10" balance="1"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM1" url="jdbc:mysql://192.168.229.215:3306" user="root"
                                   password="Test123!">
                <readHost host="hostS2" url="jdbc:mysql://192.168.229.220:3306" user="root" password="Test123!" />
                </writeHost>
        </dataHost>
        <dataHost name="host2" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM2" url="jdbc:mysql://192.168.229.211:3306" user="root"
                                   password="Test123!">
                </writeHost>
        </dataHost>
</mycat:schema>

(2)在dn2/master2创建dict_order_type表

create table dict_order_type(
id int auto_increment,
order_type varchar(200),
primary key(id)
);

(3)重启mycat

[root@mycat ~]# mycat console

(4)访问mycat向dict_order_type表插入数据

[root@mycat conf]# mysql -umycat -p123456 -h 192.168.229.187 -P 8066

mysql> use TESTDB
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

insert into dict_order_type (id,order_type) values (101,'type1');
insert into dict_order_type (id,order_type) values (102,'type2');
insert into dict_order_type (id,order_type) values (103,'type3');
insert into dict_order_type (id,order_type) values (104,'type4');
insert into dict_order_type (id,order_type) values (105,'type5');
insert into dict_order_type (id,order_type) values (106,'type6');

(5)mycat、master1、master2查看数据都是完整的。

mysql> select * from dict_order_type;
+------+------------+
| id   | order_type |
+------+------------+
|  101 | type1      |
|  102 | type2      |
|  103 | type3      |
|  104 | type4      |
|  105 | type5      |
|  106 | type6      |
+------+------------+
6 rows in set (0.04 sec)

13.常用分片规则

(1)取模
此规则是对分片字段求摸运算。也是水平分表最常用规则。
配置分表中,orders表采用了此规则。

(2)分片枚举
通过在配置文件中配置可能的枚举id,自己配置分片。
本规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国省份区县固定的,这类业务使用本条规则。
七、mycat的高可用方案

在实际项目中,mycat服务也需要考虑高可用性,如果mycat所在服务器出现宕机,或mycat服务故障,需要有备机提供服务,需要考虑mycat集群。
高可用方案
可以使用HAProxy+Keepalived配合两台mycat搭起mycat集群,实现高可用性。HAProxy实现mycat多节点的集群高可用和负载均衡,而HAProxy自身的高可用则可以通过Keepalived来实现。
1.安装配置HAProxy
HAProxy下载地址 (1)进入/usr/local/src下获取HAProxy安装包

[root@ha1 ~]# cd /usr/local/src/
[root@ha1 src]# wget https://www.haproxy.org/download/1.9/src/haproxy-1.9.16.tar.gz
[root@ha1 src]# tar zxf haproxy-1.9.16.tar.gz

进入解压后的目录,查看内核版本,进行编译。

[root@ha1 src]# cd haproxy-1.9.16/
[root@ha1 haproxy-1.9.16]# uname -r
3.10.0-1062.el7.x86_64
[root@ha1 haproxy-1.9.16]# yum -y install gcc gcc-c++
[root@ha1 haproxy-1.9.16]# make TARGET=linux310 PREFIX=/usr/local/haproxy ARCH=x86_64

参数说明

#TARGET=linux310,内核版本,使用uname -r查看内核。
#如:3.10.0-514.el7,此时该参数就为linux310;

#ARCH=x86_64,系统位数;

#PREFIX=/usr/local/haprpxy  #haprpxy安装路径。

(2)编译完成后,进行安装。

[root@ha1 haproxy-1.9.16]# make install PREFIX=/usr/local/haproxy

(3)修改配置文件

[root@ha1 haproxy-1.9.16]# vim /usr/local/haproxy/haproxy.conf
#向配置文件中插入以下配置信息,并保存
global
log 127.0.0.1 local0
#log 127.0.0.1 local1 notice
#log loghost local0 info
maxconn 4096
chroot /usr/local/haproxy
pidfile /usr/local/haproxy/haproxy.pid
uid 99
gid 99
daemon
#debug
#quiet
defaults
log global
mode tcp
option abortonclose
option redispatch
retries 3
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000
listen proxy_status
bind :48066
mode tcp
balance roundrobin
server mycat_1 192.168.229.210:8066 check inter 10s
server mycat_2 192.168.229.221:8066 check inter 10s
frontend admin_stats
bind :7777
mode http
stats enable
option httplog
maxconn 10
stats refresh 30s
stats uri /admin
stats auth admin:123123
stats hide-version
stats admin if TRUE

(4)启动HAProxy

[root@ha1 haproxy-1.9.16]# /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.conf
[root@ha1 haproxy-1.9.16]# ps -ef | grep haproxy
nobody    71716      1  0 02:16 ?        00:00:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.conf
root      71923   5549  0 02:16 pts/0    00:00:00 grep --color=auto haproxy
[root@ha1 haproxy-1.9.16]# ss -lnt
State       Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN      0      100    127.0.0.1:25                   *:*                  
LISTEN      0      10       *:7777                 *:*                  
LISTEN      0      128      *:48066                *:*                  
LISTEN      0      128      *:22                   *:*                  
LISTEN      0      100      [::1]:25                    [::]:*                  
LISTEN      0      128       [::]:22                    [::]:*

(5)浏览器访问

http://192.168.229.187:7777/admin

dble mysql中间件 mysql的中间件是什么_mysql


输入用户名:admin

密码:123123

dble mysql中间件 mysql的中间件是什么_haproxy_02


验证负载均衡,通过HAProxy访问mycat。

mysql -umycat -p123456 -h 192.168.229.187 -P 48066
mysql> use TESTDB
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------+
| Tables_in_test  |
+-----------------+
| customer        |
| dict_order_type |
| orders          |
| orders_detail   |
+-----------------+
4 rows in set (0.00 sec)

mysql> select * from orders;
+----+------------+-------------+-----------+
| id | order_type | customer_id | amount    |
+----+------------+-------------+-----------+
|  1 |        101 |         100 | 100100.00 |
|  2 |        101 |         100 | 100300.00 |
|  6 |        102 |         100 | 100020.00 |
|  3 |        101 |         101 | 120000.00 |
|  4 |        101 |         101 | 103000.00 |
|  5 |        102 |         101 | 100400.00 |
+----+------------+-------------+-----------+
6 rows in set (0.05 sec)

2.安装配置Keepalived
新开一台虚拟机安装配置haproxy,然后继续keepalived的安装部署实现高可用。
安装部署haproxy步骤如上。
keepalived下载地址 (1)进入/usr/local/src下获取Keepalived安装包

[root@ha1 haproxy-1.9.16]# cd /usr/local/src/
[root@ha1 src]# wget https://www.keepalived.org/software/keepalived-2.1.0.tar.gz
[root@ha1 src]# tar zxf keepalived-2.1.0.tar.gz

(2)安装依赖插件

yum -y install gcc gcc-c++ openssl-devel popt-devel

(3)进入解压后的目录,进行配置、编译。

[root@ha1 src]# cd keepalived-2.1.0/
[root@ha1 keepalived-2.1.0]# ./configure --prefix=/usr/local/keepalived

(4)编译完成后进行安装

[root@ha1 keepalived-2.1.0]# make && make install

(5)运行前配置

[root@ha1 keepalived-2.1.0]# cp /usr/local/src/keepalived-2.1.0/keepalived/etc/init.d/keepalived /etc/init.d/
[root@ha1 keepalived-2.1.0]# mkdir /etc/keepalived
[root@ha1 keepalived-2.1.0]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
[root@ha1 keepalived-2.1.0]# cp /usr/local/src/keepalived-2.1.0/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
[root@ha1 keepalived-2.1.0]# cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

(6)修改配置文件

[root@ha1 keepalived-2.1.0]#  vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id LVS_1
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }   
    virtual_ipaddress {
        192.168.229.100
    }   
}   

virtual_server 192.168.229.100 48066 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 192.168.229.187 48066 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }

    real_server 192.168.229.209 48066 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

(8)配置文件发给ha2一份进行修改。

[root@ha1 keepalived-2.1.0]# scp /etc/keepalived/keepalived.conf root@192.168.229.209:/etc/keepalived/
[root@ha2 keepalived-2.1.0]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id LVS_2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }   
    virtual_ipaddress {
        192.168.229.100
    }   
}   

virtual_server 192.168.229.100 48066 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 192.168.229.187 48066 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }

    real_server 192.168.229.209 48066 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

(9)ha1和ha2启动keepalived验证

[root@ha1 keepalived-2.1.0]# systemctl start keepalived
[root@ha1 keepalived-2.1.0]# ip a show dev ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:07:f1:dd brd ff:ff:ff:ff:ff:ff
    inet 192.168.229.187/24 brd 192.168.229.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.229.100/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::34cf:4139:8fca:50aa/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@ha2 keepalived-2.1.0]# ip a show dev ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:1b:30:ac brd ff:ff:ff:ff:ff:ff
    inet 192.168.229.209/24 brd 192.168.229.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::e646:793b:426a:9e2e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

(10)登录验证

[root@master1 ~]# mysql -umycat -p123456 -h 192.168.229.100 -P 48066

3.测试高可用
(1)测试关闭mycat,通过虚拟ip查询数据。

mysql -umycat -p123456 -h 192.168.140.200 -P 48066  #可以使用slave主机验证成功登录,但是master主机登录会卡住,具体原因不明。

4.挂起主ha1,查看IP地址自动飘移到ha2上。

[root@ha2 keepalived-2.1.0]# ip a show dev ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:1b:30:ac brd ff:ff:ff:ff:ff:ff
    inet 192.168.229.209/24 brd 192.168.229.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.229.100/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::e646:793b:426a:9e2e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

5.重新运行ha1,发现IP地址再次飘移回来。

[root@ha1 ~]# ip a show dev ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:07:f1:dd brd ff:ff:ff:ff:ff:ff
    inet 192.168.229.187/24 brd 192.168.229.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.229.100/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::34cf:4139:8fca:50aa/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

6.浏览器访问飘移地址

192.168.229.100:7777/admin

输入用户名:admin

密码:123123

dble mysql中间件 mysql的中间件是什么_中间件_03


4.mycat安全设置

(1)权限配置

user标签权限控制

目前mycat对于中间件的连接控制并没有做太复杂的控制,目前只做了中间件逻辑库级别的读写权限控制。通过server.xml的user标签进行配置。

[root@mycat1 conf]# vim server.xml
...
        <user name="mycat" defaultAccount="true">
                <property name="password">123456</property>
                <property name="schemas">TESTDB</property>
                <property name="defaultSchema">TESTDB</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">TESTDB</property>
                <property name="readOnly">true</property>
                <property name="defaultSchema">TESTDB</property>
        </user>

</mycat:server>

privileges标签权限控制
在user标签下的privileges标签可以对逻辑库(schema)、表(table)进行精细化的DML权限控制。
privileges标签下的check属性,如为true开启权限检查,为false不开启,默认为false。
由于mycat一个用户的schemas属性可配置多个逻辑库(schema),所以privileges的下级节点schema节点同样可配置多个,对多库多表进行细粒度的DML权限控制。

[root@mycat1 conf]# vim server.xml
#配置orders表没有增删改查权限
#privileges默认是被禁用的,需要打开它。
...
        <user name="mycat" defaultAccount="true">
                <property name="password">123456</property>
                <property name="schemas">TESTDB</property>
                <property name="defaultSchema">TESTDB</property>
                
                <!-- 表级 DML 权限设置 -->
                <privileges check="true">
                        <schema name="TESTDB" dml="1111" >
                                <table name="orders" dml="0000"></table>
                        </schema>
                </privileges>           
        </user>
...

验证

[root@mycat1 conf]# mycat stop
[root@mycat1 conf]# mycat start
[root@mycat1 conf]# mysql -umycat -p123456 -h 192.168.229.210 -P 8066

mysql> use TESTDB
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------+
| Tables_in_test  |
+-----------------+
| customer        |
| dict_order_type |
| orders          |
| orders_detail   |
+-----------------+
4 rows in set (0.00 sec)

mysql> select * from orders;
ERROR 3012 (HY000): The statement DML privilege check is not passed, reject for user 'mycat'

配置说明

DML权限

增加(insert)

更新(update)

查询(select)

删除(select)

0000

禁止

禁止

禁止

禁止

0010

禁止

禁止

可以

禁止

1110

可以

禁止

禁止

禁止

1111

可以

可以

可以

可以

(2)SQL拦截
firewall标签用来定义防火墙;firewall下whitehost标签用来定义IP白名单,blacklist用来定义SQL黑名单。
白名单:可以通过设置白名单,实现某主机某用户可以访问mycat,而其他主机用户禁止访问。
设置白名单

[root@mycat1 conf]# vim server.xml
#配置只有192.168.229.210主机可以通过mycat用户访问
...
        <firewall>
           <whitehost>
              <host host="192.168.229.210" user="mycat"/>
           </whitehost>
       <blacklist check="false">
       </blacklist>
        </firewall>
...

验证

[root@mycat1 conf]# mycat stop
[root@mycat1 conf]# mycat start
[root@mycat1 conf]# mysql -umycat -p123456 -h 192.168.229.210 -P 8066
[root@mycat2 conf]# mysql -umycat -p123456 -h 192.168.229.210 -P 8066
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (HY000): Access denied for user 'mycat' with host '192.168.229.221'

黑名单:可以通过设置黑名单,实现mycat对具体SQL操作的拦截,是比privileges更进一步的控制,如增删改查等操作的拦截。
设置黑名单

[root@mycat1 conf]# vim server.xml
#配置禁止mycat用户进行删除操作
...
        <firewall>
           <whitehost>
              <host host="192.168.229.210" user="mycat"/>
           </whitehost>
       <blacklist check="true">
        <property name="deleteAllow">false</property>
       </blacklist>
        </firewall>
...

验证

[root@mycat1 conf]# mycat stop
[root@mycat1 conf]# mycat start
[root@mycat1 conf]# mysql -umycat -p123456 -h 192.168.229.210 -P 8066

mysql> use TESTDB
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------+
| Tables_in_test  |
+-----------------+
| customer        |
| dict_order_type |
| orders          |
| orders_detail   |
+-----------------+
4 rows in set (0.00 sec)

mysql> delete from orders where id=1;
ERROR 3012 (HY000): The statement is unsafe SQL, reject for user 'mycat'

可以设置的黑名单SQL拦截功能列表

配置项

缺省值

描述

selelctAllow

true

是否允许执行SELECT语句

deleteAllow

true

是否允许执行DELETE语句

updateAllow

true

是否允许执行UPDATE语句

insertAllow

true

是否允许执行INSERT语句

createTableAllow

true

是否允许创建表

setAllow

true

是否允许使用SET语法

alterTableAllow

true

是否允许执行Alter Table语句

dropTableAllow

true

是否允许修改表

commitAllow

true

是否允许执行commit操作

rollbackAllow

true

是否允许执行rollback操作