系统开发中,数据库是很是重要的一个点。除了程序的自己的优化,如:SQL语句优化、代码优化,数据库的处理自己优化也是很是重要的。主从、热备、分表分库等都是系统发展早晚会遇到的技术问题问题。Mycat是一个广受好评的数据库中间件,已经在不少产品上进行使用了。下面就针对Mycat的基础知识和应用作一总结性梳理,这些内容有的是从网上收集的,有的是本身作的测试验证信息,若有错误,烦请谅解和指出!html
1、MyCat简单介绍
MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户能够把它看做是一个数据库代理(相似于Mysql Proxy),用MySQL客户端工具和命令行访问,而其后端能够用MySQL原生协议与多个MySQL服务器通讯,也能够用JDBC协议与大多数主流数据库服务器通讯,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其余数据库里。前端
MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端能够支持MySQL、SQL Server、Oracle、DB二、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,将来还会支持更多类型的存储。而在最终用户看来,不管是那种存储方式,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操做,这样一来,对前端业务系统来讲,能够大幅下降开发难度,提高开发速度。java
Mycat能够简单归纳为
- 一个完全开源的,面向企业应用开发的大数据库集群
- 支持事务、ACID、能够替代MySQL的增强版数据库
- 一个能够视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群
- 一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server
- 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
- 一个新颖的数据库中间件产品node
Mycat关键特性
- 支持SQL92标准
- 遵照Mysql原生协议,跨语言,跨平台,跨数据库的通用中间件代理
- 基于心跳的自动故障切换,支持读写分离,支持MySQL主从,以及galera cluster集群
- 支持Galera for MySQL集群,Percona Cluster或者MariaDB cluster
- 基于Nio实现,有效管理线程,高并发问题
- 支持数据的多片自动路由与聚合,支持sum,count,max等经常使用的聚合函数,支持跨库分页
- 支持单库内部任意join,支持跨库2表join,甚至基于caltlet的多表join
- 支持经过全局表,ER关系的分片策略,实现了高效的多表join查询
- 支持多租户方案
- 支持分布式事务(弱xa)
- 支持全局序列号,解决分布式下的主键生成问题
- 分片规则丰富,插件化开发,易于扩展
- 强大的web,命令行监控
- 支持前端做为mysq通用代理,后端JDBC方式支持Oracle、DB二、SQL Server 、 mongodb 、巨杉
- 支持密码加密
- 支持服务降级
- 支持IP白名单
- 支持SQL黑名单、sql注入攻击拦截
- 支持分表(1.6)
- 集群基于ZooKeeper管理,在线升级,扩容,智能优化,大数据处理(2.0开发版)mysql
2、为何要用MyCat
这里要先搞清楚Mycat和MySQL的区别(Mycat的核心做用)。咱们能够把上层看做是对下层的抽象,例如操做系统是对各种计算机硬件的抽象。那么咱们何时须要抽象?假如只有一种硬件的时候,咱们须要开发一个操做系统吗?再好比一个项目只须要一我的完成的时候不须要leader,可是当须要几十人完成时,就应该有一个管理者,发挥沟通协调等做用,而这个管理者对于他的上层来讲就是对项目组的抽象。linux
一样的,当咱们的应用只须要一台数据库服务器的时候咱们并不须要Mycat,而若是你须要分库甚至分表,这时候应用要面对不少个数据库的时候,这个时候就须要对数据库层作一个抽象,来管理这些数据库,而最上面的应用只须要面对一个数据库层的抽象或者说数据库中间件就行了,这就是Mycat的核心做用。因此能够这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象。web
3、Mycat工做原理
Mycat的原理并不复杂,复杂的是代码。Mycat的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句作了一些特定的分析:如分
片分析、路由分析、读写分离分析、缓存分析等,而后将此SQL发日后端的真实数据库,并将返回的结果作适当的处理,最终再返回给用户。算法
上述图片里,Orders表被分为三个分片datanode(简称dn),这三个分片是分布在两台MySQL Server上(DataHost),即datanode=database@datahost方式,所以你能够用一台到N台服务器来分片,分片规则为(sharding rule)典型的字符串枚举分片规则,一个规则的定义是分片字段(sharding column)+分片函数(rule function),这里的分片字段为prov而分片函数为字符串枚举方式。sql
当Mycat收到一个SQL时,会先解析这个SQL,查找涉及到的表,而后看此表的定义,若是有分片规则,则获取到SQL里分片字段的值,并匹配分片函数,获得该SQL对应的分片列表,而后将SQL发往这些分片去执行,最后收集和处理全部分片返回的结果数据,并输出到客户端。以select * from Orders where prov=?语句为例,查到prov=wuhan,按照分片函数,wuhan返回dn1,因而SQL就发给了MySQL1,去取DB1上的查询结果,并返回给用户。mongodb
若是上述SQL改成select * from Orders where prov in (‘wuhan’,‘beijing’),那么,SQL就会发给MySQL1与MySQL2去执行,而后结果集合并后输出给用户。但一般业务中咱们的SQL会有Order By 以及Limit翻页语法,此时就涉及到结果集在Mycat端的二次处理,这部分的代码也比较复杂,而最复杂的则属两个表的Jion问题,为此,Mycat提出了创新性的ER分片、全局表、HBT(Human Brain Tech)人工智能的Catlet、以及结合Storm/Spark引擎等十八般武艺的解决办法,从而成为目前业界最强大的方案,这就是开源的力量!
4、Mycat应用场景
Mycat发展到如今,适用的场景已经很丰富,并且不断有新用户给出新的创新性的方案,如下是几个典型的应用场景:
- 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换;
- 分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片;
- 多租户应用,每一个应用一个库,但应用程序只链接Mycat,从而不改造程序自己,实现多租户化;
- 报表系统,借助于Mycat的分表能力,处理大规模报表的统计;
- 替代Hbase,分析大数据;
- 做为海量数据实时查询的一种简单有效方案,好比100亿条频繁查询的记录须要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其余属性查询,此时Mycat多是最简单有效的选择;
- Mycat长期路线图;
- 强化分布式数据库中间件的方面的功能,使之具有丰富的插件、强大的数据库智能优化功能、全面的系统监控能力、以及方便的数据运维工具,实如今线数据扩容、迁移等高级功能;
- 进一步挺进大数据计算领域,深度结合Spark Stream和Storm等分布式实时流引擎,可以完成快速的巨表关联、排序、分组聚合等 OLAP方向的能力,并集成一些热门经常使用的实时分析算法,让工程师以及DBA们更容易用Mycat实现一些高级数据分析处理功能。
- 不断强化Mycat开源社区的技术水平,吸引更多的IT技术专家,使得Mycat社区成为中国的Apache,并将Mycat推到Apache
基金会,成为国内顶尖开源项目,最终可以让一部分志愿者成为专职的Mycat开发者,荣耀跟实力一块儿提高。
5、Mycat不适合的应用场景
- 设计使用Mycat时有非分片字段查询,请慎重使用Mycat,能够考虑放弃!
- 设计使用Mycat时有分页排序,请慎重使用Mycat,能够考虑放弃!
- 设计使用Mycat时若是要进行表JOIN操做,要确保两个表的关联字段具备相同的数据分布,不然请慎重使用Mycat,能够考虑放弃!
- 设计使用Mycat时若是有分布式事务,得先看是否得保证事务得强一致性,不然请慎重使用Mycat,能够考虑放弃!
须要注意: 在生产环境中, Mycat节点最好使用双节点, 即双机热备环境, 防止Mycat这一层出现单点故障. 可使用的高可用集群方式有: Keepalived+Mycat+Mysql, Keepalived+LVS+Mycat+Mysql, Keepalived+Haproxy+Mycat+Mysql
6、利用MyCAT实现MySQL的读写分离、主从切换、分库分表的操做记录
Mycat实现Mysql主从复制,其中写操做在master主节点上执行,包括insert,delete,update 语句操做;读操做在slave节点上执行,只有select语句操做,其余操做均由主master的二进制文件决定;MyCat支持双主多从,多主多从状况须要配置多个writeHost兄弟节点,多个readHost节点便可!
Mycat的架构其实很好理解,Mycat是数据库代理中间件,Mycat后面就是物理数据库。和Web服务器的Nginx相似。对于使用者来讲,访问的都是Mycat,不会接触到后端的数据库。以下案例是作一个主从、读写分离,简单分库分表的示例。结构以下图:
服务器信息以下(实验环境,关闭机器的iptables防火墙和selinux):
1
2
3
4
5
6
7
8
9
10
11
12
|
服务器主机名 ip 说明
Mycat-node 192.168.10.210 mycat服务器,链接数据库时,链接此服务器
Mysql-node1 192.168.10.205 物理数据库1,真正存储数据的数据库,这里为Master主数据库
Mysql-node2 192.168.10.206 物理数据库2,真正存储数据的数据库,这里为Slave主数据库
三台机器分布修改主机名,并作hosts绑定
# vim /etc/hosts
192.168.10.205 Mysql-node1
192.168.10.206 Mysql-node1
192.168.10.210 Mycat-node
为方便作实验,关闭三台机器的iptables防火墙和selinux
|
Mycat做为主数据库中间件,确定是与代码弱关联的,因此代码是不用修改的,使用Mycat后,链接数据库是不变的,默认端口是8066。链接方式和普通数据库同样,好比:jdbc:mysql://192.168.10.210:8066/
1)Mysql安装及主从复制部署(Mysql-node1和Mysql-node2两台机器上操做)
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
|
a)安装Mysql,安装过程要在两个Mysql节点机器上都要操做。
安装过程参考:http:
//www
.cnblogs.com
/kevingrace/p/6109679
.html
这里省去安装过程~~
b)Mysql主从复制(两个节点的mysql登陆用户名和密码都是root
/123456
)
参考:http:
//www
.cnblogs.com
/kevingrace/p/6256603
.html
====================================================
首先是Mysql-node1主节点配置操做
[root@Mysql-node1 ~]
# cp /usr/local/mysql/my.cnf /usr/local/mysql/my.cnf.bak
[root@Mysql-node1 ~]
# vim /usr/local/mysql/my.cnf #在[mysqld]区域添加下面内容
......
[mysqld]
server-
id
=1
log-bin=mysql-bin
#binlog-do-db=kevin #须要同步的数据库。若是是多个同步库,就以此格式另写几行便可。若是不指明对某个具体库同步,就去掉此行,表示同步全部库(除了ignore忽略的库)
binlog-ignore-db = mysql,information_schema
sync_binlog = 1
binlog_checksum = none
binlog_format = mixed
重启mysql服务
[root@Mysql-node1 ~]
# /etc/init.d/mysql restart
登陆mysql,授予slave从机复制权限
mysql> grant replication slave,replication client on *.* to slave@
'192.168.10.206'
identified by
"slave@123"
;
Query OK, 0 rows affected (0.05 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.06 sec)
受权以后,要保证192.168.10.206这台slave节点机器能使用上面的权限信息登陆到本机的mysql
将数据库锁住,仅仅容许读,以保证数据一致性;
mysql> FLUSH TABLES WITH READ LOCK;
#注意,锁定后,若是本身同步对方数据,同步前必定要记得先解锁!
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.05 sec)
查看主节点的master复制信息
mysql> show master status;
+------------------+----------+--------------+--------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 | 1349 | | mysql,information_schema | |
+------------------+----------+--------------+--------------------------+-------------------+
1 row
in
set
(0.00 sec)
====================================================
接着是slave从节点操做
[root@Mysql-node2 ~]
# cp /usr/local/mysql/my.cnf /usr/local/mysql/my.cnf.bak
[root@Mysql-node2 ~]
# vim /usr/local/mysql/my.cnf
.......
[mysqld]
.......
server-
id
=2
log-bin=mysql-bin
#replicate-do-db=kevin #须要同步的数据库名。若是不指明同步哪些库,就去掉这行,表示全部库的同步(除了ignore忽略的库)。
replicate-ignore-db=mysql
slave-skip-errors = all
重启mysql服务
[root@Mysql-node2 ~]
# /etc/init.d/mysql restart
登陆slave节点的mysql,进行主从同步设置
mysql> stop slave;
Query OK, 0 rows affected (0.09 sec)
mysql> change master to master_host=
'192.168.10.205'
,master_user=
'slave'
,master_password=
'slave@123'
,master_log_file=
'mysql-bin.000003'
,master_log_pos=1349;
Query OK, 0 rows affected, 2 warnings (0.21 sec)
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting
for
master to send event
Master_Host: 192.168.10.205
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 1349
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
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: 1349
Relay_Log_Space: 456
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: 747977ea-8fba-11e8-86c0-525400b19c93
Master_Info_File:
/data/mysql/data/master
.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has
read
all relay log; waiting
for
the slave I
/O
thread to update it
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
1 row
in
set
(0.00 sec)
ERROR:
No query specified
mysql>
=========================================================
经过上面的信息,可知主从复制环境已经OK(Slave_IO_Running和Slave_SQL_Running状态均为YES),下面验证下主从复制是否正常?
在Mysql-node1主节点上操做
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE DATABASE kevin CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.06 sec)
mysql> use kevin;
Database changed
mysql> create table
if
not exists haha (
id
int(10) PRIMARY KEY AUTO_INCREMENT,name varchar(50) NOT NULL);
Query OK, 0 rows affected (0.34 sec)
在Mysql-node2从节点上查看(保证从节点上查看slave状态时,Slave_IO_Running和Slave_SQL_Running状态均为YES,这样就能保证主从复制在进行中)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kevin |
| mysql |
| performance_schema |
|
test
|
+--------------------+
5 rows
in
set
(0.00 sec)
mysql> use kevin;
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_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
接着在Mysql-node1主节点插入数据
mysql> insert into kevin.haha values(1,
"wangshibo"
),(2,
"linan"
),(3,
"zhangminmin"
);
Query OK, 3 rows affected (0.04 sec)
Records: 3 Duplicates: 0 Warnings: 0
而后再在MYsql-node2从节点查看,以下发现已经同步过来了!
mysql> use kevin;
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows
in
set
(0.00 sec)
因而可知,Mysql的主从复制已经实现!
|
2)Mycat中间件安装、配置和测试(Mycat-node节点机器上操做)
2.1)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
|
建议下载1.6-RELEASE 版本,毕竟是比较稳定的版本。
下载官网地址:http:
//dl
.mycat.io/
[root@Mycat-node ~]
# cd /usr/local/src/
[root@Mycat-node src]
# wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@Mycat-node src]
# tar -zvxf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@Mycat-node src]
# mv mycat /data/
[root@Mycat-node src]
# ls /data/mycat/
bin catlet conf lib logs version.txt
mycat安装完成后,目录以下:
bin mycat命令,启动、重启、中止等
catlet catlet为Mycat的一个扩展功能
conf Mycat 配置信息,重点关注
lib Mycat引用的jar包,Mycat是java开发的
logs 日志文件,包括Mycat启动的日志和运行的日志。
Mycat的配置文件都在conf目录里面,这里介绍几个经常使用的文件:
server.xml Mycat的配置文件,设置帐号、参数等
schema.xml Mycat对应的物理数据库和数据库表的配置
rule.xml Mycat分片(分库分表)规则
[root@Mycat-node src]
# cd /data/mycat/conf
[root@Mycat-node conf]
# ll server.xml
-rwxrwxrwx. 1 root root 3740 Jul 25 12:19 server.xml
[root@Mycat-node conf]
# ll schema.xml
-rwxrwxrwx. 1 root root 4667 Jul 31 02:54 schema.xml
|
2.2)Mycat相关配置
server.xml文件其实跟读写分离策略关系不大,可是须要用此文件来配置链接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
|
[root@Mycat-node conf]
# cp server.xml server.xml.bak
[root@Mycat-node conf]
# vim server.xml
.......
<user name=
"bobo"
>
<property name=
"password"
>bo@123<
/property
>
<property name=
"schemas"
>mycat
/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
>
<!--
#注意,因为这里只定义了一个标签,因此把多余的都注释了。若是这个打开,也须要将TESTDB库改成和上面同样的mycat库名。
<user name=
"user"
>
<property name=
"password"
>user<
/property
>
<property name=
"schemas"
>TESTDB<
/property
>
<property name=
"readOnly"
>
true
<
/property
>
<
/user
>
-->
<
/mycat
:server>
.......
重点关注上面这段配置,其余默认便可。
=======================================
参数 说明
user 用户配置节点
name 登陆的用户名,也就是链接Mycat的用户名。
password 登陆的密码,也就是链接Mycat的密码
schemas 数据库名,这里会和schema.xml中的配置关联,多个用逗号分开,例如须要这个用户须要管理两个数据库db1,db2,则配置db1,dbs
privileges 配置用户针对表的增删改查的权限
readOnly mycat逻辑库所具备的权限。
true
为只读,
false
为读写都有,默认为
false
。
=======================================
我这里配置了一个帐号boo,密码为bo@123,逻辑数据库为mycat,这些信息均可以本身随意定义,读写权限都有,没有针对表作任何特殊的权限。
注意:
- server.xml文件里登陆mycat的用户名和密码能够任意定义,这个帐号和密码是为客户机登陆mycat时使用的帐号信息。
- 逻辑库名(如上面的mycat,也就是登陆mycat后显示的库名,切换这个库以后,显示的就是代理的真实mysql数据库的表)要在schema.xml里面也定义,不然会致使mycat服务启动失败!
- 这里只定义了一个标签,因此把多余的都注释了。若是定义多个标签,即设置多个链接mycat的用户名和密码,那么就须要在schema.xml文件中定义多个对应的库!
|
schema.xml是最主要的配置项,此文件关联mysql读写分离策略!读写分离、分库分表策略、分片节点都是在此文件中配置的!
MyCat做为中间件,它只是一个代理,自己并不进行数据存储,须要链接后端的MySQL物理服务器,此文件就是用来链接MySQL服务器的!
schemaxml文件中配置的参数解释
1
2
3
4
|
参数 说明
schema 数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应
dataNode 分片信息,也就是分库相关配置
dataHost 物理数据库,真正存储数据的数据库
|
配置说明
1
2
3
4
|
name属性惟一标识dataHost标签,供上层的标签使用。
maxCon属性指定每一个读写实例链接池的最大链接。也就是说,标签内嵌套的
writeHost、readHost标签都会使用这个属性的值来实例化出链接池的最大链接数。
minCon属性指定每一个读写实例链接池的最小链接,初始化链接池的大小。
|
每一个节点的属性逐一说明
1
2
3
4
5
|
schema:
属性 说明
name 逻辑数据库名,与server.xml中的schema对应
checkSQLschema 数据库前缀相关设置,建议看文档,这里暂时设为folse
sqlMaxLimit
select
时默认的limit,避免查询全表
|
table
1
2
3
4
5
6
|
属性 说明
name 表名,物理数据库中表名
dataNode 表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name
primaryKey 主键字段名,自动生成主键时须要设置
autoIncrement 是否自增
rule 分片规则名,具体规则下文rule详细介绍
|
dataNode
1
2
3
4
|
属性 说明
name 节点名,与table中dataNode对应
datahost 物理数据库名,与datahost中name对应
database 物理数据库中数据库名
|
dataHost
1
2
3
4
5
6
|
属性 说明
name 物理数据库名,与dataNode中dataHost对应
balance 均衡负载的方式
writeType 写入方式
dbType 数据库类型
heartbeat 心跳检测语句,注意语句结尾的分号要加
|
schema.xml文件中有三点须要注意:balance="1",writeType="0" ,switchType="1"
schema.xml中的balance的取值决定了负载均衡对非事务内的读操做的处理。balance 属性负载均衡类型,目前的取值有 4 种:
1
2
3
4
5
6
7
8
9
10
|
balance=
"0"
: 不开启读写分离机制,全部读操做都发送到当前可用的writeHost 上,即读请求仅发送到writeHost上。
balance=
"1"
: 读请求随机分发到当前writeHost对应的readHost和standby的writeHost上。即所有的readHost与stand by writeHost 参与
select
语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 , M2->S2,而且 M1 与 M2 互为主备),正常状况下, M2,S1,
S2 都参与
select
语句的负载均衡
balance=
"2"
: 读请求随机分发到当前dataHost内全部的writeHost和readHost上。即全部读操做都随机的在writeHost、 readhost 上分发。
balance=
"3"
: 读请求随机分发到当前writeHost对应的readHost上。即全部读请求随机的分发到 wiriterHost 对应的 readhost 执行,
writerHost 不负担读压力,注意 balance=3 只在 1.4 及其之后版本有,1.3 没有。
|
writeType 属性,负载均衡类型,目前的取值有 3 种
1
2
3
|
writeType=
"0"
全部写操做发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost,从新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .
writeType=
"1"
全部写操做都随机的发送到配置的 writeHost。
writeType=
"2"
没实现。
|
对于事务内的SQL默认走写节点
1
2
3
4
5
|
以 /*balance*/ 开头,能够指定SQL使用特定负载均衡方案。例如在大环境开启读写分离的状况下,特定强一致性的SQL查询需求;
slaveThreshold:近似的主从延迟时间(秒)Seconds_Behind_Master < slaveThreshold ,读请求才会分发到该Slave,确保读到的数据相对较新。
schema.xml中的writeType的取值决定了负载均衡对写操做的处理:
writeType=
"0"
:全部的写操做都发送到配置文件中的第一个write host。(第一个write host故障切换到第二个后,即便以后修复了仍然维持第二个为写库)。推荐取0值,不建议修改.
|
主从切换(双主failover):switchType 属性
1
2
3
4
5
6
7
8
|
若是细心观察schem.xml文件的话,会发现有一个参数:switchType,以下配置:
<dataHost name=
"237_15"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
参数解读
switchType=
"-1"
: 不自动切换
switchType=
"1"
: 默认值,自动切换
switchType=
"2"
: 基于MySQL主从同步的状态来决定是否切换。需修改heartbeat语句(即心跳语句):show slave status
switchType=
"3"
: 基于Mysql Galera Cluster(集群多节点复制)的切换机制。需修改heartbeat语句(即心跳语句):show status like
'wsrep%'
|
dbType属性
1
|
指定后端链接的数据库类型,目前支持二进制的mysql协议,还有其余使用JDBC链接的数据库。例如:mongodb、oracle、spark等。
|
dbDriver属性指定链接后端数据库使用的
1
2
3
4
5
6
7
|
Driver,目前可选的值有native和JDBC。
使用native的话,由于这个值执行的是二进制的mysql协议,因此可使用mysql和maridb。
其余类型的数据库则须要使用JDBC驱动来支持。从1.6版本开始支持postgresql的native原始协议。
若是使用JDBC的话须要将符合JDBC 4标准的驱动JAR包放到MYCAT\lib目录下,并检查驱动JAR包中包括以下目录结构的文件:
META-INF\services\java.sql.Driver。在这个文件内写上具体的Driver类名,例如:com.mysql.jdbc.Driver。
|
heartbeat标签
1
2
3
4
5
6
|
这个标签内指明用于和后端数据库进行心跳检查的语句。例如,MYSQL可使用
select
user(),Oracle可使用
select
1 from dual等。
这个标签还有一个connectionInitSql属性,主要是当使用Oracla数据库时,须要执行的初始化SQL
语句就这个放到这里面来。例如:altersession
set
nls_date_format=
'yyyy-mm-dd hh24:mi:ss'
1.4主从切换的语句必须是:showslave status
|
writeHost标签、readHost标签
1
2
3
4
5
6
|
这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端链接池。
惟一不一样的是:writeHost指定写实例、readHost指定读实例,组着这些读写实例来知足系统的要求。
在一个dataHost内能够定义多个writeHost和readHost。可是,若是writeHost指定的后端数据库宕机,那么这个writeHost绑定的全部readHost都将不可用。
另外一方面,因为这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去。
|
应用场景1--->Mycat读写分离(负载均衡)、主从自动切换
目前有大量Mycat的生产实践案例是属于简单的读写分离类型的,此案例主要用到Mycat的如下特性:
- 读写分离支持
- 高可用
大多数读写分离的案例是同时支持高可用性的,即Mycat+MySQL主从复制的集群,并开启Mycat的读写分离功能,这种场景需求下,Mycat是最为简单而且功能最为
丰富的一类Proxy,正常状况下,配置文件也最为简单,不用每一个表配置,只须要在schema.xml中的元素上增长dataNode=“defaultDN”属性,并配置此dataNode
对应的真实物理数据库的database,而后dataHost开启读写分离功能便可。
修改mycat的schema.xml:
balance为1:让所有的readHost及备用的writeHost参与select的负载均衡。
switchType为2:基于MySQL主从同步的状态决定是否切换。
heartbeat:主从切换的心跳语句必须为show slave status。
仅仅进行读写分离的schema.xml配置(备份原来的schema.xml文件,清空,直接复制下面内容):不想要自动切换功能,即MySQL写节点宕机后不自动切换到备用节点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[root@Mycat-node conf]
# vim schema.xml
<?xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM
"schema.dtd"
>
<mycat:schema xmlns:mycat=
"http://io.mycat/"
>
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
dataNode=
"haha"
>
<
/schema
>
<dataNode name=
"haha"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataHost name=
"Mycat-node"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
<heartbeat>show slave status<
/heartbeat
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.205:3306"
user=
"root"
password=
"123456"
>
<readHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/readHost
>
<
/writeHost
>
<
/dataHost
>
<
/mycat
:schema>
|
实现主从自动切换的schema.xml配置:即MySQL写节点宕机后自动切换到备用节点(也就是把从机也配置成writeHosts):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@Mycat-node conf]
# vim schema.xml
<?xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM
"schema.dtd"
>
<mycat:schema xmlns:mycat=
"http://io.mycat/"
>
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
dataNode=
"haha"
>
<
/schema
>
<dataNode name=
"haha"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataHost name=
"Mycat-node"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
<heartbeat>show slave status<
/heartbeat
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.205:3306"
user=
"root"
password=
"123456"
>
<readHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/readHost
>
<
/writeHost
>
<writeHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/writeHost
>
<
/dataHost
>
<
/mycat
:schema>
|
上面配置中,balance改成1,表示读写分离。
以上配置达到的效果就是192.168.10.205为主库,192.168.10.206为从库。
注意:要保证192.168.10.205和192.168.10.206机器能使用root/123456权限成功登陆mysql数据库。同时,也必定要受权mycat机器能使用root/123456权限成功登陆这两台机器的mysql数据库!!这很重要,不然会致使登陆mycat后,对库和表操做失败!
一主一从结构是最简单的配置。
MyCat支持双主多从,若是有N个主,那么就配置N个writeHost兄弟节点;若是有M个从节点,那么就配置M个readHost节点便可。
也能够有多台MySQL服务器,或者SQL Server、Oracle等,配置多个dataHost节点就能够。
须要注意的是:
Mycat主从分离只是在读的时候作了处理,写入数据的时候,只会写入到writehost,须要经过mycat的主从复制将数据复制到readhost!这个问题须要弄明白!!
若是没有提早作mysql主从复制,会发现Mycat读写分离配置后,数据写入writehost后,readhost一直没有数据!由于Mycat就没有实现主从复制的功能,毕竟数据库自己自带的这个功能才是最高效稳定的。
特别注意:
1
2
3
4
5
6
7
8
9
10
11
|
1)本案例采用的一主一从模式的两个mysql实例,而且针对单一的数据库名进行测试;大多数mycat使用场景都是在多主多从模式并针对多个库进行的。
2)要想登陆Mycat后看到mysql的真实数据库的表内容,须要在schema.xml文件中指明database,其中dataNote和dataHost名称能够自定义,database名称要是mysql上的库名。
3)若是针对的是mysql的多个库,好比mysql的真实库名是kevin、grace、shanshan,那么schema.xml文件里应该指明多个库名,如:
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
dataNode=
"haha,heihei,hengheng"
>
<
/schema
>
<dataNode name=
"haha"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataNode name=
"heihei"
dataHost=
"Mycat-node"
database=
"grace"
/>
<dataNode name=
"hengheng"
dataHost=
"Mycat-node"
database=
"shanshan"
/>
........
4)主从自动切换配置后,第一个writeHost故障后,会自动切换到第二个,第二个故障后自动切换到第三个;
若是当是1主3从模式,能够把第1个从节点配置为writeHost 2,第2个和第3个从节点则配置为writeHost 1的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
|
[root@Mycat-node ~]
# cd /data/mycat/bin/
[root@Mycat-node bin]
#
[root@Mycat-node bin]
# ./mycat start #开启
[root@Mycat-node bin]
# ./mycat stop #关闭
[root@Mycat-node bin]
# ./mycat restart #重启
[root@Mycat-node bin]
# ./mycat status #查看启动状态
[root@Mycat-node bin]
# ./mycat console #前台运行
[root@Mycat-node bin]
# ./mycat pause #暂停
mycat启动后,执行命令不成功,可能实际上配置有错误,致使后面的命令没有很好的执行。
若是在启动时发现异常,在logs目录中查看日志。
[root@Mycat-node ~]
# cd /data/mycat/logs/
[root@Mycat-node logs]
# ls
2018-07 mycat.log mycat.pid wrapper.log
- wrapper.log 为程序启动的日志,启动时的问题看这个
- mycat.log 为脚本执行时的日志,SQL脚本执行报错后的具体错误内容,查看这个文件。mycat.log是最新的错误日志,历史日志会根据时间生成目录保存。
[root@Mycat-node conf]
# cd /data/mycat/bin/
[root@Mycat-node bin]
# ./mycat start
Starting Mycat-server...
[root@Mycat-node bin]
# ps -ef|grep cat
root 5693 1 0 11:28 ? 00:00:00
/data/mycat/bin/
.
/wrapper-linux-x86-64
/data/mycat/conf/wrapper
.conf wrapper.syslog.ident=mycat wrapper.pidfile=
/data/mycat/logs/mycat
.pid wrapper.daemonize=TRUE wrapper.lockfile=
/var/lock/subsys/mycat
root 5695 5693 58 11:28 ? 00:00:01 java -DMYCAT_HOME=. -server -XX:MaxPermSize=64M -XX:+AggressiveOpts -XX:MaxDirectMemorySize=2G -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1984 -Dcom.sun.management.jmxremote.authenticate=
false
-Dcom.sun.management.jmxremote.ssl=
false
-Xmx4G -Xms1G -Djava.library.path=lib -classpath lib
/wrapper
.jar:conf:lib
/zookeeper-3
.4.6.jar:lib
/velocity-1
.7.jar:lib
/disruptor-3
.3.4.jar:lib
/hamcrest-library-1
.3.jar:lib
/curator-client-2
.11.0.jar:lib
/mysql-binlog-connector-java-0
.4.1.jar:lib
/curator-framework-2
.11.0.jar:lib
/wrapper
.jar:lib
/log4j-1
.2.17.jar:lib
/kryo-2
.10.jar:lib
/objenesis-1
.2.jar:lib
/log4j-core-2
.5.jar:lib
/log4j-1
.2-api-2.5.jar:lib
/log4j-slf4j-impl-2
.5.jar:lib
/leveldb-api-0
.7.jar:lib
/minlog-1
.2.jar:lib
/mongo-java-driver-2
.11.4.jar:lib
/netty-3
.7.0.Final.jar:lib
/sequoiadb-driver-1
.12.jar:lib
/libwrapper-linux-x86-64
.so:lib
/curator-recipes-2
.11.0.jar:lib
/dom4j-1
.6.1.jar:lib
/commons-lang-2
.6.jar:lib
/guava-19
.0.jar:lib
/commons-collections-3
.2.1.jar:lib
/reflectasm-1
.03.jar:lib
/slf4j-api-1
.6.1.jar:lib
/joda-time-2
.9.3.jar:lib
/jline-0
.9.94.jar:lib
/libwrapper-linux-x86-32
.so:lib
/leveldb-0
.7.jar:lib
/Mycat-server-1
.6-RELEASE.jar:lib
/jsr305-2
.0.3.jar:lib
/libwrapper-linux-ppc-64
.so:lib
/univocity-parsers-2
.2.1.jar:lib
/hamcrest-core-1
.3.jar:lib
/log4j-api-2
.5.jar:lib
/asm-4
.0.jar:lib
/mapdb-1
.0.7.jar:lib
/fastjson-1
.2.12.jar:lib
/druid-1
.0.26.jar:lib
/ehcache-core-2
.6.11.jar -Dwrapper.key=ZcN0KgylpD8RMkUx -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=5693 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp io.mycat.MycatStartup start
root 5729 24581 0 11:29 pts
/0
00:00:00
grep
cat
Mycat服务端口默认是8066
[root@Mycat-node bin]
# lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 5695 root 79u IPv6 37036522 0t0 TCP *:8066 (LISTEN)[root@Mycat-node conf]
# lsof -i:9066
Mycat还有一个管理端口,默认是9066
[root@Mycat-node conf]
# lsof -i:9066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 5695 root 75u IPv6 37036520 0t0 TCP *:9066 (LISTEN)
|
在客户机远程登陆Mycat登陆mysql(将mycat启动起来后,远程链接,默认端口是8066,逻辑库名和帐号密码就是在schema.xml里配置的信息。代码里用jdbc方式链接)
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
|
Mycat带来的最大好处就是:
使用是彻底不用修改原有代码的,在mycat经过命令启动后,你只须要将数据库链接切换到Mycat的地址就能够了。
以下面就能够进行链接了(注意使用server.xml文件中定义的用户名和密码链接mycat)
登陆mycat的前提是:两台mysql机器要受权mycat服务器使用root
/123456
成功登陆这两个mysql。
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection
id
is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, 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 |
+----------+
| mycat |
+----------+
1 row
in
set
(0.01 sec)
mysql> use mycat;
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_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows
in
set
(0.00 sec)
mysql>
|
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
将mycat的日志输出级别改完debug(默认是info级别),在conf
/log4j2
.xml里配置,而后去查询去添加数据在
/logs/mycat
.log日志文件里查看sql被路由到了
哪一个服务器上
特别注意:查询语句不要加事务,不然读操做会被分发到写服务器上。
[root@Mycat-node ~]
# vim /data/mycat/conf/log4j2.xml
......
把
<asyncRoot level=
"info"
includeLocation=
"true"
>
改为
<asyncRoot level=
"debug"
includeLocation=
"true"
>
重启mycat服务
[root@Mycat-node ~]
# /data/mycat/bin/mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@Mycat-node ~]
# lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 18955 root 79u IPv6 3812293 0t0 TCP *:8066 (LISTEN)
登陆mycat
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection
id
is 2
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, 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 |
+----------+
| mycat |
+----------+
1 row
in
set
(0.00 sec)
mysql> use mycat;
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_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows
in
set
(0.00 sec)
mysql>
经过mycat写入一条数据或读数据,查看sql被路由到了代理的哪一个mysql服务器上了:
mysql> insert into kevin.haha values(4,
"lihuan"
);
Query OK, 1 row affected (0.31 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows
in
set
(0.01 sec)
mysql>
而后查看mycat.log的debug日志,观察mysql的sql被路由到了哪一个服务器上了(下面日志中的192.168.10.203是远程客户机的ip地址)。
[root@Mycat-node ~]
# tail -f /data/mycat/logs/mycat.log
.......
2018-07-31 08:50:12.616 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.execute(NonBlockingSession.java:110)) - ServerConnection
[
id
=2, schema=mycat, host=192.168.10.203, user=bobo,txIsolation=3, autocommit=
true
, schema=mycat]insert into kevin.haha values(4,
"lihuan"
),
route={
1 -> haha{insert into kevin.haha values(4,
"lihuan"
)}
.......
.......
2018-07-31 08:50:12.617 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) -
con need syn ,total syn cmd 1 commands SET names latin1;schema change:
false
con:MySQLConnection [
id
=6, lastTime=1532998212617, user=root,
schema=kevin, old shema=kevin, borrowed=
true
, fromSlaveDB=
false
, threadId=55, charset=latin1, txIsolation=3, autocommit=
true
, attachment=
haha{insert into kevin.haha values(4,
"lihuan"
)}, respHandler=SingleNodeHandler [node=haha{insert into kevin.haha values(4,
"lihuan"
)}, packetId=0],
host=192.168.10.205, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
true
]
.......
.......
2018-07-31 08:50:14.358 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [
id
=12, lastTime=1532998214353, user=root, schema=kevin, old shema=kevin, borrowed=
true
, fromSlaveDB=
true
,
threadId=29, charset=latin1, txIsolation=3, autocommit=
true
, attachment=haha{
select
* from haha}, respHandler=SingleNodeHandler [node=haha
{
select
* from haha}, packetId=8], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
false
]
从日志中能够看出,
"insert into ...."
插入语句路由到了192.168.10.205的主机上了,
"select * ..."
的查询语句路由到了192.168.10.206的从机上了。
这就实现了mysql的读写分离!!
|
Mycat主从自动切换测试(采用上面自动切换的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
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
|
首先关闭主机192.168.10.205的mysql服务,此时从机192.168.10.206的mysql已经失去了和主机192.168.10.205的mysql主从关系。
[root@Mysql-node1 ~]
# /etc/init.d/mysql stop
Shutting down MySQL............ SUCCESS!
[root@Mysql-node1 ~]
# lsof -i:3306
[root@Mysql-node1 ~]
#
[root@Mysql-node2 ~]
# mysql -p123456
........
mysql> show slave status \G;
*************************** 1. row ***************************
.......
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
.......
Last_IO_Error: error reconnecting to master
'slave@192.168.10.205:3306'
- retry-
time
: 60 retries: 1
而后客户机登陆mycat进行读写操做
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
......
mysql> use mycat;
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_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows
in
set
(0.00 sec)
mysql> insert into kevin.haha values(5,
"gengmei"
);
Query OK, 1 row affected (0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 5 | gengmei |
+----+-------------+
5 rows
in
set
(0.00 sec)
同时查看mycat.log的debug日志,观察读写操做都被路由到哪里了:
[root@Mycat-node ~]
# tail -f /data/mycat/logs/mycat.log
.......
2018-07-31 09:10:19.261 INFO [$_NIOConnector] (io.mycat.net.AbstractConnection.close(AbstractConnection.java:508)) - close connection,reason:java.net.
ConnectException: Connection refused ,MySQLConnection [
id
=0, lastTime=1532999419254, user=root, schema=kevin, old shema=kevin, borrowed=
false
, fromSlaveDB=
false
,
threadId=0, charset=utf8, txIsolation=3, autocommit=
true
, attachment=null, respHandler=null, host=192.168.10.205, port=3306, statusSync=null, writeQueue=0,
modifiedSQLExecuted=
false
]
2018-07-31 09:10:19.261 INFO [$_NIOConnector] (io.mycat.sqlengine.SQLJob.connectionError(SQLJob.java:114)) - can't get connection
for
sql :show slave status
.......
2018-07-31 09:06:20.139 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [
id
=17, lastTime=1532999180134, user=root, schema=kevin, old shema=kevin, borrowed=
true
, fromSlaveDB=
false
,
threadId=46, charset=latin1, txIsolation=3, autocommit=
true
, attachment=haha{insert into kevin.haha values(5,
"gengmei"
)}, respHandler=SingleNodeHandler
[node=haha{insert into kevin.haha values(5,
"gengmei"
)}, packetId=1], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
true
]
......
2018-07-31 09:06:21.727 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) - con need syn ,total
syn cmd 1 commands SET names latin1;schema change:
false
con:MySQLConnection [
id
=16, lastTime=1532999181727, user=root, schema=kevin, old shema=kevin, borrowed
=
true
, fromSlaveDB=
false
, threadId=48, charset=latin1, txIsolation=3, autocommit=
true
, attachment=haha{
select
* from haha}, respHandler=SingleNodeHandler [node=
haha{
select
* from haha}, packetId=0], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
false
]
从上面的日志中能够看出,主机192.168.10.205已经断开从mycat链接,insert写语句和
select
读语句都被路由分配到了从机192.168.10.206的mysql上了,
这就看出来已经实现了mysql主从启动切换了!!!
登陆从机192.168.10.206的mysql,发现新插入的数据已经写进去了
[root@Mysql-node2 ~]
# mysql -p123456
.......
mysql> use kevin;
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 kevin.haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 5 | gengmei |
+----+-------------+
5 rows
in
set
(0.00 sec)
mysql>
|
Mycat分表分库的原理
mycat里面经过定义路由规则来实现分片表(路由规则里面会定义分片字段,以及分片算法)。分片算法有多种,你所说的hash是其中一种,还有取模、按范围分片等等。在mycat里面,会对全部传递的sql语句作路由处理(路由处理的依据就是表是否分片,若是分片,那么须要依据分片字段和对应的分片算法来判断sql应该传递到哪个、或者哪几个、又或者所有节点去执行)
Mycat适用于哪些场景?
数据量大到单机hold不住,而又不但愿调整架构切换为NoSQL数据库,这个场景下能够考虑适用mycat。固然,使用前也应该作规划,哪些表须要分片等等。另外mycat对跨库join的支持不是很好,在使用mycat的时候要注意规避这种场景。
应用场景2--->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
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
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
接着上面的操做继续:
启动主机192.168.10.205的mysql
[root@Mysql-node1 ~]
# /etc/init.d/mysql start
Starting MySQL... SUCCESS!
[root@Mysql-node1 ~]
# lsof -i:3306
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
mysqld 11645 mysql 17u IPv4 10457025 0t0 TCP *:mysql (LISTEN)
mysqld 11645 mysql 39u IPv4 10457749 0t0 TCP Mysql-node1:mysql->Mycat-node:39252 (ESTABLISHED)
mysqld 11645 mysql 40u IPv4 10458099 0t0 TCP Mysql-node1:mysql->Mysql-node1:57270 (ESTABLISHED)
登陆从机192.168.10.206的mysql,重启slave的主从同步关系
[root@Mysql-node2 ~]
# mysql -p123456
......
mysql> show slave status \G;
......
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
......
Last_IO_Error: error reconnecting to master
'slave@192.168.10.205:3306'
- retry-
time
: 60 retries: 81
......
mysql> stop slave;
Query OK, 0 rows affected (0.08 sec)
mysql> start slave;
Query OK, 0 rows affected (0.04 sec)
mysql> show slave status \G;
......
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
.....
在主机192.168.10.205的mysql上再建立一个数据库grace
如今须要将haha表放在kevin库里,将heihei表拆分放到kevin和grace库了。
操做以下(在主机mysql里操做,从机mysql自动会同步过来):
登陆grace库里建立heihei表,同时在kevin库里也建立heihei表。
特别须要注意的是:
- 分表的表在建立时必定要建立主键,不然在mycat端写入数据时会报错主键冲突!!
- 分表的表要在两个库上都要建立。
mysql> CREATE DATABASE grace CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
mysql> use grace;
Database changed
mysql> CREATE TABLE heihei (
->
id
INT NOT NULL AUTO_INCREMENT,
-> city varchar(50) NOT NULL,
-> PRIMARY KEY (
id
)
-> )AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.23 sec)
mysql> insert into grace.heihei values(1,
"beijing"
);
Query OK, 1 row affected (0.03 sec)
mysql> show tables;
+-----------------+
| Tables_in_grace |
+-----------------+
| heihei |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from grace.heihei;
+----+---------+
|
id
| name |
+----+---------+
| 1 | beijing |
+----+---------+
1 row
in
set
(0.00 sec)
mysql> use kevin;
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_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql> CREATE TABLE heihei (
->
id
INT NOT NULL AUTO_INCREMENT,
-> city varchar(50) NOT NULL,
-> PRIMARY KEY (
id
)
-> )AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.23 sec)
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
| heihei |
+-----------------+
2 rows
in
set
(0.00 sec)
mysql> insert into kevin.heihei values(1,
"shanghai"
);
Query OK, 1 row affected (0.13 sec)
mysql>
select
* from kevin.heihei;
+----+----------+
|
id
| name |
+----+----------+
| 1 | shanghai |
+----+----------+
1 row
in
set
(0.00 sec)
上面在从机的mysql里操做后,从机的mysql会自动把数据同步过来!
登陆mycat机器192.168.10.210机器,分别设置server.xml文件、rule.xml文件、schema.xml文件
server.xml文件在上面已经设置过了,这里就不用修改了:
[root@Mycat-node ~]
# vim /data/mycat/conf/server.xml
......
<!-- mycat的服务端口默认为8066,管理端口默认为9066 -->
<property name=
"serverPort"
>8066<
/property
> <property name=
"managerPort"
>9066<
/property
>
.....
<!-- 任意设置登录 mycat 的用户名,密码,数据库 -->
<user name=
"bobo"
>
<property name=
"password"
>bo@123<
/property
>
<property name=
"schemas"
>mycat<
/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 name=
"user"
>
<property name=
"password"
>user<
/property
>
<property name=
"schemas"
>TESTDB<
/property
>
<property name=
"readOnly"
>
true
<
/property
>
<
/user
>
-->
<
/mycat
:server>
分库分表配置还涉及到rule.xml文件,配置以下(备份文件,清空,直接复制下面内容):
[root@Mycat-node conf]
# cp rule.xml rule.xml.bak
[root@Mycat-node conf]
# vim rule.xml
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!-- - - Licensed under the Apache License, Version 2.0 (the
"License"
);
- you may not use this
file
except
in
compliance with the License. - You
may obtain a copy of the License at - - http:
//www
.apache.org
/licenses/LICENSE-2
.0
- - Unless required by applicable law or agreed to
in
writing, software -
distributed under the License is distributed on an
"AS IS"
BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License
for
the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:rule SYSTEM
"rule.dtd"
>
<mycat:rule xmlns:mycat=
"http://io.mycat/"
>
<tableRule name=
"mycat-rule"
> <!-- heihei表分片的规则名,这里定义为mycat-rule,这个须要在schema.xml文件中引用 -->
<rule>
<columns>
id
<
/columns
> <!--heihei表的分片列 -->
<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
> <!-- count值与分片个数相同,这里heihei表分片到kevin库和grace库里,共2份。 -->
<
/function
>
<
/mycat
:rule>
接着配置schema.xml文件(server.xml文件配置在已经已经完成),分库分表配置以下
(要将rule.xml里定义的分片模型写进去,因为这里的heihei表配置了主键,因此primaryKey=
"id"
这个也写进去,其余状况看表结构,也能够不写):
[root@Mycat-node conf]
# cp schema.xml schema.xml.old
[root@Mycat-node conf]
# vim schema.xml
<?xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM
"schema.dtd"
>
<mycat:schema xmlns:mycat=
"http://io.mycat/"
>
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
>
<table name=
"haha"
primaryKey=
"id"
dataNode=
"kevin_db"
/>
<table name=
"heihei"
primaryKey=
"id"
dataNode=
"kevin_db,grace_db"
rule=
"mycat-rule"
/>
<
/schema
>
<dataNode name=
"kevin_db"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataNode name=
"grace_db"
dataHost=
"Mycat-node"
database=
"grace"
/>
<dataHost name=
"Mycat-node"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
<heartbeat>show slave status<
/heartbeat
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.205:3306"
user=
"root"
password=
"123456"
>
<readHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/readHost
>
<
/writeHost
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/writeHost
>
<
/dataHost
>
<
/mycat
:schema>
重启mycat服务
[root@Mycat-node conf]
# /data/mycat/bin/mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@Mycat-node conf]
# lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 971 root 79u IPv6 4024290 0t0 TCP *:8066 (LISTEN)
[root@Mycat-node conf]
# lsof -i:9066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 971 root 75u IPv6 4024288 0t0 TCP *:9066 (LISTEN)
在客户机远程登陆Mycat
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection
id
is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, 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 |
+----------+
| mycat |
+----------+
1 row
in
set
(0.01 sec)
mysql> use mycat;
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
mycat |
+-----------------+
| haha |
| heihei |
+-----------------+
2 rows
in
set
(0.01 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows
in
set
(0.12 sec)
mysql>
select
* from heihei;
+----+----------+
|
id
| city |
+----+----------+
| 1 | beijing |
| 1 | shanghai |
+----+----------+
2 rows
in
set
(0.04 sec)
mysql>
分别在mycat里往heihei和grace.heihei表里插入一些数据
mysql> insert into haha values(10,
"wangbiao"
);
insert into haha values(11,
"zhangcaiyi"
);Query OK, 1 row affected (0.06 sec)
mysql> insert into haha values(11,
"zhangcaiyi"
);
Query OK, 1 row affected (0.06 sec)
mysql> insert into heihei(
id
,city) values(20,
"chognqing"
);
Query OK, 1 row affected (0.09 sec)
mysql> insert into heihei(
id
,city) values(22,
"xianggang"
);
insert into heihei(
id
,city) values(28,
"chengdu"
);Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei(
id
,city) values(23,
"huoqiu"
);
Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei(
id
,city) values(24,
"haikou"
);
Query OK, 1 row affected (0.03 sec)
mysql> insert into heihei(
id
,city) values(25,
"anqing"
);
Query OK, 1 row affected (0.03 sec)
mysql> insert into heihei(
id
,city) values(26,
"tianqing"
);
Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei(
id
,city) values(27,
"hangzhou"
);
Query OK, 1 row affected (0.04 sec)
mysql> insert into heihei(
id
,city) values(28,
"chengdu"
);
Query OK, 1 row affected (0.26 sec)
特别注意:
1)在配置了sharding分片策略以后(如heihei表),mycat里分片的表作插入数据时,即便插入全部字段的数据,也必定要在表名后面写明插入数据的字段名称,
不然插入数据会报错:ERROR 1064 (HY000): partition table, insert must provide ColumnList
2)没有配置sharding分片策略的表(如haha表),插入全部字段的数据时,表名后面不须要写明字段名称,默认就是全部字段插入数据,如上面的haha表。
登陆主机和从机,查看从mycat端写入的数据
mysql>
select
* from kevin.haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 10 | wangbiao |
| 11 | zhangcaiyi |
+----+-------------+
6 rows
in
set
(0.00 sec)
mysql>
select
* from grace.heihei;
+----+-----------+
|
id
| city |
+----+-----------+
| 1 | beijing |
| 21 | guangzhou |
| 23 | huoqiu |
| 25 | anqing |
| 27 | hangzhou |
+----+-----------+
5 rows
in
set
(0.00 sec)
mysql>
select
* from kevin.heihei;
+----+-----------+
|
id
| city |
+----+-----------+
| 1 | shanghai |
| 20 | chognqing |
| 22 | xianggang |
| 24 | haikou |
| 26 | tianqing |
| 28 | chengdu |
+----+-----------+
6 rows
in
set
(0.00 sec)
mysql>
从上面能够看出:
在mycat里往作了sharding分片策略的heihei表里写入的数据,已经分片到kevin和grace两个库里了,即成功实现了分库分表功能!
查看mycat的debug日志,能够观察到mysql读写分离和分库分表状况
[root@Mycat-node logs]
# tail -f mycat.log
|
这里须要注意:
- 查询语句不要加事务,不然读操做会被分发到写服务器上。
- 主从复制是mysql本身实现的,mycat只是代理插件,它自己不能实现主从复制,只能实现了读写分离、主从切换、分库分表功能。
为了提高查询的性能,有人创新的设计了一种MySQL主从复制的模式,主节点为InnoDB引擎,读节点为MyISAM引擎,通过实践,发现查询性能提高很多。
此外,为了减小主从复制的时延,也建议采用MySQL 5.6+的版本,用GTID同步复制方式减小复制的时延,能够将一个Database中的表,根据写频率的不一样,
分割成几个Database,用Mycat虚拟为一个Database,这样就知足了多库并发复制的优点,须要注意的是,要将有Join关系的表放在同一个库中。
对于某些表,要求不能有复制时延,则能够考虑这些表放到Gluster集群里,消除同步复制的时延问题,前提是这些表的修改操做并不很频繁,须要作性能测试,
以确保能知足业务高峰。
总结一下,Mycat作读写分离和高可用,可能的方案很灵活,只有你没想到的,没有作不到的。
=================Mycat常见问题及注意点==================
1)Mycat自动切换须要人工处理么?
Mycat经过心跳检测,自主切换数据库,保证高可用性,无须手动切换。
2)Mycat支持集群么?
目前Mycat没有实现对多Mycat集群的支持,能够暂时使用haproxy来作负载,或者统计硬件负载。
3)Mycat目前有生产案例了么?
目前Mycat初步统计大概600家公司使用。
4)Mycat稳定性与Cobar如何?
目前Mycat稳定性优于Cobar,并且一直在更新,Cobar已经中止维护,能够放心使用。
5)Mycat除了Mysql还支持哪些数据库?
mongodb、oracle、sqlserver 、hive 、db2 、 postgresql。
6)Mycat如何配置字符集?
在配置文件server.xml配置,默认配置为utf8。
7)Mycat后台管理监控如何使用?
9066端口能够用JDBC方式执行命令,在界面上进行管理维护,也能够经过命令行查看命令行操做。
命令行操做是:mysql -h127.0.0.1 -utest -ptest -P9066 登录,而后执行相应命令。
8)Mycat主键插入后应用如何获取?
得到自增主键,插入记录后执行select last_insert_id()获取。
9)Mycat运行sql时常常阻塞或卡死是什么缘由?
若是出现执行sql语句长时间未返回,或卡死,请检查是不是虚机下运行或cpu为单核。若是仍旧没法解决,能够暂时跳过,目前有些环境阻塞卡死缘由未知。
10)Mycat中,旧系统数据如何迁移到Mycat中?
旧数据迁移目前能够手工导入,在mycat中提取配置好分配规则及后端分片数据库,而后经过dump或loaddata方式导入,后续Mycat就作旧数据自动数据迁移工具。
11)Mycat如何对旧分片数据迁移或扩容,支持自动扩容么?
目前除了一致性hash规则分片外其余数据迁移比较困难,目前暂时能够手工迁移,未提供自动迁移方案,具体迁移方案状况Mycat权威指南对应章节。
12)Mycat支持批量插入吗?
目前Mycat1.3.0.3之后支持多values的批量插入,如insert into(xxx) values(xxx),(xxx) 。
13)Mycat支持多表Join吗?
Mycat目前支持2个表Join,后续会支持多表Join,具体Join请看Mycat权威指南对应章节。
14)Mycat 启动报主机不存在的问题?
须要添加ip跟主机的映射。
15)Mycat链接会报无效数据源(Invalid datasource)?
例如报错:mysql> select * from company;
ERROR 3009 (HY000): java.lang.IllegalArgumentException: Invalid DataSource:0
这类错误最多见是一些配置问题例如schema.xml中的dataNode的配置和实际不符合,请先仔细检查配置项,确保配置没有问题。
若是不是配置问题,分析具体日志看出错缘由,常见的有:
- 若是是应用连:在某些版本的Mysql驱动下链接Mycat会报错,可升级最新的驱动包试下。
- 若是是服务端控制台连,确认mysql是否开启远程链接权限,或防火墙是否设置正确,或者数据库database是否配置,或用户名密码是否正确。
16)Mycat支持的或者不支持的语句有哪些?
insert into,复杂子查询,3表及其以上跨库join等不支持。
17)MycatJDBC链接报 PacketTooBigException异常
检查mysqljdbc驱动的版本,在使用mycat1.3和mycat1.4版本状况下,不要使用jdbc5.1.37和38版本的驱动,会出现以下异常报错:
com.mysql.jdbc.PacketTooBigException: Packet for query is too large (60 > -1). You can change this value on the server by setting the max_allowed_packet’ variable。
建议使用jdbc5.1.35或者36的版本。
18)Mycat中文乱码的问题
答:若是在使用mycat出现中文插入或者查询出现乱码,请检查三个环节的字符集设置:
a)客户端环节(应用程序、mysql命令或图形终端工具)链接mycat字符集
b)mycat链接数据库的字符集
c)数据库(mysql,oracle)字符集。这三个环节的字符集若是配置一致,则不会出现中文乱码,其中尤为须要注意的是客户端链接mycat时使用的链接字符集,
一般的中文乱码问题通常都由此处设置不当引出。其中mycat内部默认使用utf8字符集,在最初启动链接数据库时,mycat会默认使用utf8去链接数据库,当客户
端真正链接mycat访问数据库时,mycat会使用客户端链接使用的字符集修改它链接数据库的字符集,在mycat环境的管理9066端口,能够经过"show @@backend"命令
查看后端数据库的链接字符集,经过show @@connection命令查看前端客户端的链接字符集。客户端的链接能够经过指定字符集编码或者发送SET命令指定链接mycat
时connection使用的字符集,常见客户端链接指定字符集写法以下:
- jdbcUrl=jdbc:mysql://localhost:8066/databaseName? characterEncoding=iso_1
- SET character_set_client = utf8;用来指定解析客户端传递数据的编码
SET character_set_results = utf8;用来指定数据库内部处理时使用的编码
SET character_set_connection = utf8;用来指定数据返回给客户端的编码方式
- mysql –utest –ptest –P8066 –default-character-set=gbk
19)Mycat没法登录Access denied
Mycat正常安装配置完成,登录mycat出现如下错误:
[mysql@master ~]$ mysql -utest -ptest -P8066
ERROR 1045 (28000): Access denied for user 'test’@’localhost’ (using password: YES)
请检查在schema.xml中的相关dataHost的mysql主机的登录权限,通常都是由于配置的mysql的用户登录权限不符合,mysql用户权限管理不熟悉的请本身度娘。
只有一种状况例外,mycat和mysql主机都部署在同一台设备,其中主机localhost的权限配置正确,使用-hlocalhost能正确登录mysql可是没法登录mycat的状况,
请使用-h127.0.0.1登录,或者本地网络实际地址,不要使用-hlocalhost,不少使用者反馈此问题,缘由未明。
20)Mycat的分片数据插入报异常IndexOutofBoundException
在一些配置了分片策略的表进行数据插入时报错,常见的报错信息以下:java.lang.IndexOutOfBoundsException:Index:4,size:3
这类报错一般因为分片策略配置不对引发,请仔细检查并理解分片策略的配置,例如:使用固定分片hash算法,PartitionByLong策略,若是schema.xml里面设置
的分片数量dataNode和rule.xml配置的partitionCount 分片个数不一致,尤为是出现分片数量dataNode小于partitionCount数量的状况,插入数据就可能会报错。
不少使用者都没有仔细理解文档中对分片策略的说明,用默认rule.xml配置的值,没有和本身实际使用环境进行参数核实就进行分片策略使用形成这类问题居多。
21)Mycat ER分片子表数据插入报错
通常都是插入子表时出现不能找到父节点的报错。报错信息如: [Err] 1064 - can’t find (root) parent sharding node for sql:。
此类ER表的插入操做不能作为一个事务进行数据提交,若是父子表在一个事务中进行提交,显然在事务没有提交前子表是没法查到父表的数据的,所以就没法肯定
sharding node。若是是ER关系的表在插入数据时不能在同一个事务中提交数据,只能分开提交。
22)Mycat最大内存没法调整至4G以上
mycat1.4的JVM使用最大内存调整若是超过4G大小,不能使用wrapper.java.maxmemory参数,须要使用wrapper.java.additional的写法,注意将
wrapper.java.maxmemory参数注释,例如增长最大内存至8G:wrapper.java.additional.10=-Xmx8G。
23)Mycat使用过程当中报错怎么办
记住不管何时遇到报错,若是不能第一时间理解报错的缘由,首先就去看日志,不管是启动(wrapper.log)仍是运行过程当中(mycat.log),请相信良好的
日志是编程查错的终极必杀技。日志若是记录信息不够,能够调整conf/log4j.xml中的level级别至debug,全部的详细信息均会记录。另外若是在群里面提问,
尽可能将环境配置信息和报错日志提供清楚,这样别人才能快速帮你定位问题。