linux下MyCat实现MySQL8.0数据分库存储

本文详细介绍了在CentOS8环境下,如何安装与配置Mycat1.6.7.6,包括下载、解压、配置schema.xml、rule.xml和server.xml等步骤。同时,针对Mycat与MySQL8.0数据库的连接问题,分析了因驱动版本不匹配导致的错误,并提供了解决方案。最后,展示了如何通过Navicat连接并测试Mycat的分片功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境

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&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;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&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;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&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;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中
添加数据后数据添加到不同的数据库中

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值