MyCAT 分表实践

前言

当我们的数据库的数据量增大一定程度后,会导致性能大幅度下降。通常可以采用MyCAT来实现数据库的分表分库,这篇来简单记录一下如何实现,后面再来分析MyCAT的源码

MyCAT实践

运行环境:Windows + MyCAT1.6,两台MySQL服务,以及一台MyCAT服务器。

MySQL1 10.1.13.29

MySQL2 10.1.13.30

MyCAT 10.66.83.213

首先到官网下载MyCAT。在conf文件夹中有三个文件比较重要,分别为schema.xmlserver.xmlrule.xml

server.xml 主要配置逻辑数据库的信息,包括用户名、密码、端口等,也是代码中数据库连接的地址。我们通过连接这个逻辑数据库,来操作物理数据库,这个逻辑数据库配置完毕可以直接在navicat看到:

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
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE MyCAT:server SYSTEM "server.dtd">
<MyCAT:server xmlns:MyCAT="http://io.MyCAT/">
<system>
<!-- 1为开启实时统计、0为关闭 -->
<property name="useSqlStat">0</property>
<!-- 1为开启全加班一致性检测、0为关闭 -->
<property name="useGlobleTableCheck">0</property>
<property name="sequnceHandlerType">2</property>
<property name="processorBufferPoolType">0</property>
<property name="handleDistributedTransactions">0</property>
<!--off heap for merge/order/group/limit 1开启 0关闭-->
<property name="useOffHeapForMerge">1</property>
<!--单位为m-->
<property name="memoryPageSize">1m</property>
<!--单位为k-->
<property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<!--单位为m-->
<property name="systemReserveMemorySize">384m</property>
<!--是否采用zookeeper协调切换 -->
<property name="useZKSwitch">true</property>
</system>

<!--配置逻辑数据库 -->
<user name="root">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
</user>

</MyCAT:server>

在这里我们配置了逻辑数据库的用户名为root,密码为123456,操作的数据库为TESTDB。

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
<?xml version="1.0"?>
<!DOCTYPE MyCAT:schema SYSTEM "schema.dtd">
<MyCAT:schema xmlns:MyCAT="http://io.MyCAT/">

<!-- 这里的schema需要和你在server.xml中逻辑数据库配置的name一样 -->
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!-- table表示你要操作的是哪张表,如配置所示,要操作的是TESTDB下的MyCATTestTable表-->
<!-- dataNode表示:TESTDB.MyCATTestTable的逻辑表对应的具体的物理节点,意思就是说操作TESTDB.MyCATTestTable表会关联到dn1.dn2-->
<!-- rule表示要逻辑表到物理表的路由策略,具体下面看-->
<table name="MyCATTestTable" dataNode="dn1,dn2" rule="mod-long />
</schema>

<!-- 配置dataNode的具体信息,dataHost为节点的连接用户名、密码等 -->
<!-- database表示要操作具体节点下的哪个数据库,这里没有指定表,是因为已经默认操作MyCATTestRealDB.MyCATTestTable -->
<dataNode name="dn1" dataHost="Host29" database="MyCATTestRealDB" />
<dataNode name="dn2" dataHost="Host30" database="MyCATTestRealDB" />


<!-- 配置物理数据的IP、户名、密码-->
<!-- heartbeat表示心跳检测的命令 -->
<!-- 配置29 -->
<dataHost name="Host29" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user();</heartbeat>
<writeHost host="hostM1" url="10.1.13.29:3306" user="root" password="tdlabDatabase">
</writeHost>
</dataHost>

<!-- 配置30 -->
<dataHost name="Host30" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user();</heartbeat>
<writeHost host="hostS1" url="10.1.13.30:3306" user="root" password="123456">
</writeHost>
</dataHost>

</MyCAT:schema>

rule.xml主要配置路由策略、拆分规则等,下面截取了mod-long的配置,常用的几种策略,可以点击这里查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MyCAT:rule SYSTEM "rule.dtd">
<MyCAT:rule xmlns:MyCAT="http://io.MyCAT/">

<tableRule name="mod-long">
<rule>
<columns>id</columns>
<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>
</function>

</MyCAT:rule>

配置完毕,在bin下启动startup-nowrap.bat

你想输入的替代文字

使用Navicat查看具体的情况:

你想输入的替代文字

你想输入的替代文字

你想输入的替代文字

往29,30插入几条数据,然后通过连接MyCAT来查看是否成功:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding: utf-8 -*-
import MySQLdb as mdb
import sys
reload(sys)
sys.setdefaultencoding('utf8')

def getSubjectCode():
con_code = mdb.connect(host='10.66.83.213', port=8066, user='root', passwd='123456', db='TESTDB', charset='utf8')
cur_code = con_code.cursor()
selectSQL = "SELECT words FROM `MyCATtesttable`;"
cur_code.execute(selectSQL)
rows = cur_code.fetchall()
subjectAreasCodes = []
for each in rows:
subjectAreasCodes.append(each[0])
return subjectAreasCodes

if __name__ == '__main__':
result = getSubjectCode()
for w in result:
print w

可以看到的确查到了29,30的数据:

你想输入的替代文字

同样的往MyCAT插入数据,因为我们采用了mod-long的路由方法,所以会根据配置的字段进行取模运算,然后插入到具体的数据库中。

参考文章

常用的分片规则