数据库分库分表有两个种方式
- 垂直切分
一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面。
优点:- 拆分后业务清晰,拆分规则明确;
- 系统之间整合或扩展容易;
- 数据维护简单。
缺点: - 部分业务表无法 join,只能通过接口方式解决,提高了系统复杂度;
- 受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高;
- 事务处理复杂。
由于垂直切分是按照业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决。
- 水平切分
相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,如图:
优点:- 拆分规则抽象好,join 操作基本可以数据库做;
- 不存在单库大数据,高并发的性能瓶颈;
- 应用端改造较少;
- 提高了系统的稳定性跟负载能力。
缺点: - 拆分规则难以抽象;
- 分片事务一致性难以解决;
- 数据多次扩展难度跟维护量极大;
- 拆分规则难以抽象;
- 分片事务一致性难以解决;
等等还有很多。具体的就参照Mycat的问题说明。还有Mycat支持的分片策略:
http://www.mycat.io/document/mycat-definitive-guide.pdf
基于Mycat用枚举分片算法实现分库
创建三个数据库
修改配置文件,如果觉得手动输入比较慢,可以直接复制然后修改库名和连接信息就可以
schema.xml配置
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- testdb是mycat的逻辑库名称,链接需要用的 -->
<schema name="testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<!--rule对应rule.xml name的名称 -->
<table name="t_user" dataNode="dn1,dn2,dn3" rule="role2" />
</schema>
<!-- database 是MySQL数据库的库名 -->
<dataNode name="dn1" dataHost="localhost1" database="t_user1" />
<dataNode name="dn2" dataHost="localhost1" database="t_user2" />
<dataNode name="dn3" dataHost="localhost1" database="t_user3" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- 可以配置多个主从 -->
<writeHost host="hostM1" url="192.168.100.131:3306" user="root" password="root">
<!-- 可以配置多个从库 -->
<readHost host="hostS2" url="192.168.100.132:3306" user="root" password="root" />
</writeHost>
</dataHost>
</mycat:schema>
rule.xml配置
<mycat:rule xmlns:mycat="http://io.mycat/">
<tableRule name="role2">
<rule>
<!-- 根据传入的name字段来判断存入那个库 -->
<columns>name</columns>
<!-- 指定的规则 -->
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
<!-- 指定的规则枚举文件 -->
<property name="mapFile">partition-hash-int.txt</property>
<!-- key 如果是数值就写0,不是就写1 -->
<property name="type">1</property>
<!-- 如果都不符合,默认存入1节点库中 -->
<property name="defaultNode">1</property>
</function>
</mycat:rule>
partition-hash-int.txt配置 key是name对应的值,value指的是存在哪个库中
hefei=0
nanjing=1
bengbu=2
server.xml配置
<mycat:server xmlns:mycat="http://io.mycat/">
<!-- 读写都可用的用户 -->
<user name="root" defaultAccount="true">
<property name="password">root</property>
<property name="schemas">testdb</property>
</user>
<!-- 只读用户 -->
<user name="user">
<property name="password">user</property>
<property name="schemas">testdb</property>
<property name="readOnly">true</property>
</user>
</mycat:server>
这样配置完成,然后启动Mycat。使用Navicat连接的时候还是会出现表找不到的原因
通过日志可以看到,每次查询表的时候都会携带逻辑库的名字。所以导致没有查询到。这个问题我还没有解决。只能通过写sql来查询和新增了。
新增四个地区名称
INSERT INTO t_user (name) VALUES ('shanghai');
INSERT INTO t_user (name) VALUES ('nanjing');
INSERT INTO t_user (name) VALUES ('hefei');
INSERT INTO t_user (name) VALUES ('bengbu');
这样就可以看出来效果了
还有很多分片策略都可以在Mycat官方指南上面看到。
http://www.mycat.io/document/mycat-definitive-guide.pdf