环境
CentOS8 192.168.21.134
jdk1.8
MyCat1.6.7.6
host1:
数据库1:MySQL8.0 10.132.84.149
库名:db1,db3
host2:
数据库2:MySQL8.0 192.168.21.128
库名:db2
两个数据库的大小写敏感最好一致
1安装MyCat
下载myCat 官网下载 链接: http://dl.mycat.io
或
链接: https://pan.baidu.com/s/1ILlDRJMyeS_wwWMv9gDpcw
提取码: bmyr
文件上传到服务器
移动到/user/local 目录下
解压
tar -zxvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz
解压后再当前目录下就解压出一个mycat文件夹
2配置MyCat
在mycat/conf目录下进行配置文件配置
常用目录:
schema.xml:定义逻辑库,表,分片节点等内容
rule.xml:定义分片规则
server.xml:定义用户以及系统相关变量
配置schema.xml
先上配置完成内容
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
<table name="t_province" primaryKey="id" dataNode="dn1,dn2,dn3" rule="sharding-by-province" autoIncrement="true" fetchStoreNodeByJdbc="true">
</table>
</schema>
<dataNode name="dn1" dataHost="host1" database="db1" />
<dataNode name="dn2" dataHost="host2" database="db2" />
<dataNode name="dn3" dataHost="host1" database="db3" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://10.132.84.149:3306?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=UTC" user="root"
password="123456">
</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="hostM1" url="jdbc:mysql://192.168.21.128:3306?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=UTC" user="root"
password="123456">
</writeHost>
</dataHost>
</mycat:schema>
重要标签解释:
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
name #Mycat库名
<table name="t_province" primaryKey="id" dataNode="dn1,dn2,dn3" rule="sharding-by-province" autoIncrement="true" fetchStoreNodeByJdbc="true">
name #表名,是有这里定义了的表才能在mycat上进行创建
dataNode #当前表所使用的节点,多个节点使用逗号添加,与后面定义的dataNode的name一致
rule #rule.xml里面定义的分片规则tableRule的name属性对应的值
autoIncrement 自增id
fetchStoreNodeByJdbc 启用ER表使用JDBC方式获取DataNode
<dataNode name="dn1" dataHost="host1" database="db1" />
name#用于区分节点
dataHost#用于绑定节点所在数据库属性,与后面定义的dataHost的name一致
database#用于定义当前节点连接的具体的库,所连接的库必须在对应dataHhost连接的数据库中存在
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://10.132.84.149:3306?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=UTC" user="root"
password="123456">
</writeHost>
</dataHost>
name#用于区分连接的数据库
url#数据库所在的地址
user#数据库账号
password#数据库密码
balance用于设置读写分离的
balance=“0”, 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
balance=“1”,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
balance=“2”,所有读操作都随机的在writeHost、readhost上分发。
balance=“3”,所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力,注意 balance=3 只在 1.4 及其以后版本有, 1.3 没有。
writeType用于设置写操作
writeType=“0”, 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .
writeType=“1”,所有写操作都随机的发送到配置的 writeHost。
writeType=“2”,没实现。-1 表示不自动切换1 默认值,自动切换2 基于MySQL 主从同步的状态决定是否切换
配置分片规则 rule.xml
<tableRule name="sharding-by-province">
<rule>
<columns>province</columns>
<algorithm>province-hash</algorithm>
</rule>
</tableRule>
<function name="province-hash"
class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">sharding-by-province.txt</property>
<property name="type">1</property>
<property name="defaultNode">0</property>
</function>
重要标签解释
sharding-by-province#规则名,会在schema.xml中用到
columns#指的是对省份(province字段)进行分片
algorithm#算法名,该算法必须在function中定义
mapFile#配置文件名
type#默认值为0,0表示Integer,非零表示String。因为测试是基于省份分片,所以需type指定为1。
defaultNode#默认节点:小于0表示不设置默认节点,大于等于0表示设置默认节点
默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点。如果不配置默认节点(defaultNode值小于0表示不配置默认节点),碰到不识别的枚举值就会报错
配置分片对应的配置文件sharding-by-province.txt
hubei=0
tianjin=1
guangdong=2
解释
在插入数据时province字段遇到不同的数据分片到不同的dataNode中
更多配置信息参考Mycat 核心配置详解
启动项目
此时执行启动mycat
mycat支持的命令有{console|start|stop|restart|status|dump}
./bin/mycat console 控制台启动
./bin/mycat start 后台启动
mycat成功启动但是连接不上去或者启动不了
查看log文件
cat logs/mycat.log
出现异常
2021-04-02 10:31:46.224 ERROR [Timer0] (io.mycat.backend.jdbc.JDBCHeartbeat.heartbeat(JDBCHeartbeat.java:123)) - JDBCHeartBeat error
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server.
at sun.reflect.GeneratedConstructorAccessor14.newInstance(Unknown Source) ~[?:?]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_181]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_181]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:389) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.Util.getInstance(Util.java:372) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:958) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2316) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2069) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:794) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at sun.reflect.GeneratedConstructorAccessor11.newInstance(Unknown Source) ~[?:?]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_181]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_181]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:389) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at java.sql.DriverManager.getConnection(DriverManager.java:664) ~[?:1.8.0_181]
at java.sql.DriverManager.getConnection(DriverManager.java:247) ~[?:1.8.0_181]
at io.mycat.backend.jdbc.JDBCDatasource.getConnection(JDBCDatasource.java:125) ~[Mycat-server-1.6.7.6-release.jar:?]
at io.mycat.backend.jdbc.JDBCHeartbeat.heartbeat(JDBCHeartbeat.java:108) [Mycat-server-1.6.7.6-release.jar:?]
at io.mycat.backend.datasource.PhysicalDatasource.doHeartbeat(PhysicalDatasource.java:464) [Mycat-server-1.6.7.6-release.jar:?]
at io.mycat.backend.datasource.PhysicalDBPool.doHeartbeat(PhysicalDBPool.java:436) [Mycat-server-1.6.7.6-release.jar:?]
at io.mycat.MycatServer$8$1.run(MycatServer.java:964) [Mycat-server-1.6.7.6-release.jar:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
Caused by: java.lang.NullPointerException
at com.mysql.jdbc.ConnectionImpl.getServerCharset(ConnectionImpl.java:2989) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sendConnectionAttributes(MysqlIO.java:1873) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1802) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1206) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2239) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2270) ~[mysql-connector-java-5.1.35.jar:5.1.35]
... 19 more
因为mycat使用的mysql驱动版本与mysql版本不匹配
解决方法:下载mysql8.0版本的驱动进行替换
mysql-connector-java-8.0.19.jar 提取码: r6dq
删除lib目录下原版的驱动
rm -rf mysql-connector-java-5.1.35.jar
上传新版本到lib目录里面
再次启动mycat
启动成功,尝试用navicat连接(和连接mysql方式一样,账号密码在server.xml文件最下面)
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="defaultSchema">TESTDB</property>
</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>
如果发现连接不上,请查看8066端口是否开放
vim /etc/sysconfig/iptables
添加端口
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8066 -j ACCEPT
重启防火墙
service iptables restart
尝试在navicat连接的mycat的TESTDB数据库上创建表t_province
create table t_province(id varchar(10),province varchar(10));
dataNode对应的database属性定义的库中会同时创建相应的表
添加数据
insert into t_province(id,province) values(database(),'hubei');
insert into t_province(id,province) values(database(),'tianjin');
insert into t_province(id,province) values(database(),'guangdong');
insert into t_province(id,province) values(database(),'shandong');
province字段中不同的值根据定义的规则(sharding-by-province.txt)添加到了不同的数据库中
shangdong因为不存在分片规则中,则添加到定义的默认节点(defaultNode)0中