分库分表:Sharding-JDBC,mycat
1、关于分表(这里指的肯定是水平分表)
在我的思路中 如果要实现分表,首先要考虑每条记录以什么样的规则来区分放到哪一张表中。最直接的方式就是以某个字段或者某些字段通过某种算法来得出一个结果,对应到一张表中。
假设user 表。字段 有 id(int) , name(varchar) , age(int)
1.1增加数据
如果就以id作为分表因子分两张表。那可以定义规则 id % 2 得出结果 0 或者1 这里就可以对应两张表 user_0 user_1 然后对应的将这条数据插入到表中。
假设id 是 1
1%2 = 1
所以要执行的sql
INSERT INTO `user_1` VALUES (1, 'test1', 10);
1.2查询数据
如果要做数据查询 。依然还是要确定要操作那张表。
依然以 id%2 的结果来确定操作那个表
比如 id = 2
2 % 2 = 0
所以执行的sql
select * from 'user_0' where id = 2;
2、关于分库
这里假设有两个 库 db0 db1
之后要做的事情就是 定义分库规则。
借鉴分表的思路 就可以用id做因子 然后 id%2 做规则确定操作那个数据库。
如果数据中的user表依然要分 user_0 user_1
那可以制定 user.age 作为分表因子 user.age%2 做规则。具体的思路跟上面的分表一样。
分库的时候 就是需要两个规则 来确定需要操作的 库 和 表。
3、关于分表分库的应用
我这个菜鸡,假设要实践,会有不小的麻烦 首先一点就是代码的入侵太严重。之前使用的
select * from user where id = ?;
就要修改为
if(id%2 == 0){
select * from user_0 where id = ?;
}else{
select * from user_1 where id = ?;
}
而且 如果某一天 变成了分三张表就要对应的修改代码。这里的举例是最简单的语句。项目中肯定不会这么简单。所以一旦修改了分表规则,那将是噩梦般的工作量。而且ORM框架几乎就是不可用了。
4、关于分表分库的应用 中间件的查找和对比
网上关于这方面的资料我找了些。引用https://www.cnblogs.com/wangzhongqiu/p/7100332.html
反正我没啥耐心意义去自己测试这些中间件。基本上选定了两个方案。mycat,Sharding-JDBC
1>Cobar 是提供关系型数据库(MySQL)分布式服务的中间件,它可以让传统的数据库得到良好的线性扩展,并看上去还是一个数据库,对应用保持透明。Cobar以Proxy的形式位于前台应用和实际数据库之间,对前台的开放的接口是MySQL通信协议,将前台SQL语句变更并按照数据分布规则发到合适的后台数据分库,再合并返回结果,模拟单库下的数据库行为。Cobar属于中间层方案,在应用程序和MySQL之间搭建一层Proxy。中间层介于应用程序与数据库间,需要做一次转发,而基于JDBC协议并无额外转发,直接由应用程序连接数据库,性能上有些许优势。这里并非说明中间层一定不如客户端直连,除了性能,需要考虑的因素还有很多,中间层更便于实现监控、数据迁移、连接管理等功能。Cobar属于阿里B2B事业群,始于2008年,在阿里服役3年多,接管3000+个MySQL数据库的schema,集群日处理在线SQL请求50亿次以上。由于Cobar发起人的离职,Cobar停止维护。后续的类似中间件,比如MyCAT建立于Cobar之上,包括现在阿里服役的RDRS其中也复用了Cobar-Proxy的相关代码。2>MyCAT是社区爱好者在阿里cobar基础上进行二次开发,解决了cobar当时存 在的一些问题,并且加入了许多新的功能在其中。目前MyCAT社区活 跃度很高,目前已经有一些公司在使用MyCAT。总体来说支持度比 较高,也会一直维护下去,发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL, SQL Server, Oracle, [DB2](http://www.2cto.com/database/DB2/), PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。MyCAT是一个强大的数据库中间件,不仅仅可以用作读写分离,以及分表分库、容灾管理,而且可以用于多租户应用开发、云平台基础设施,让你的架构具备很强的适应性和灵活性,借助于即将发布的MyCAT只能优化模块,系统的数据访问瓶颈和热点一目了然,根据这些统计分析数据,你可以自动或手工调整后端存储,将不同的表隐射到不同存储引擎上,而整个应用的代码一行也不用改变。MyCAT是在Cobar基础上发展的版本,两个显著提高:后端由BIO改为NIO,并发量有大幅提高; 增加了对Order By, Group By, Limit等聚合功能(虽然Cobar也可以支持Order By, Group By, Limit语法,但是结果没有进行聚合,只是简单返回给前端,聚合功能还是需要业务系统自己完成)3>TDDL是Tabao根据自己的业务特点开发了(Tabao Distributed Data Layer, 外号:头都大了)。主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制,它是一个基于集中式配置的jdbc datasourcce实现,具有主备,读写分离,动态数据库配置等功能。TDDL并非独立的中间件,只能算作中间层,处于业务层和JDBC层中间,是以Jar包方式提供给应用调用,属于JDBC Shard的思想。TDDL源码:[https://github.com/alibaba/tb_tddl](https://github.com/alibaba/tb_tddl)
TDDL复杂度相对较高。当前公布的文档较少,只开源动态数据源,分表分库部分还未开源,还需要依赖diamond,不推荐使用。4>DRDS是阿里巴巴自主研发的分布式数据库服务(此项目不开源),DRDS脱胎于阿里巴巴开源的Cobar分布式数据库引擎,吸收了Cobar核心的Cobar-Proxy[源码](http://www.2cto.com/ym/),实现了一套独立的类似MySQL-Proxy协议的解析端,能够对传入的SQL进行解析和处理,对应用程序屏蔽各种复杂的底层DB拓扑结构,获得单机数据库一样的使用体验,同时借鉴了淘宝TDDL丰富的分布式数据库实践经验,实现了对分布式Join支持,SUM/MAX/COUNT/AVG等聚合函数支持以及排序等函数支持,通过异构索引、小表广播等解决分布式数据库使用场景下衍生出的一系列问题,最终形成了完整的分布式数据库方案。5>Atlas是一个位于应用程序与MySQL之间的*基于MySQL协议的数据中间层项目*,**它是在mysql-proxy 0.8.2版本上对其进行优化,**360团队基于mysql proxy 把lua用C改写,*****它实现了MySQL的客户端和服务端协议,**作为服务端与应用程序通讯,同时作为客户端与MySQL通讯。它对应用程序屏蔽了DB的细节。**Altas不能实现分布式分表,所有的字表必须在同一台DB的同一个DataBase里且所有的字表必须实现建好,Altas没有自动建表的功能。**原有版本是不支持分库分表, 目前已经放出了分库分表版本。在网上看到一些朋友经常说在高并 发下会经常挂掉,如果大家要使用需要提前做好测试。*6>DBProxy是美团点评DBA团队针对公司内部需求,在奇虎360公司开源的Atlas做了很多改进工作,形成了新的高可靠、高可用企业级数据库中间件其特性主要有:读写分离、负载均衡、支持分表、IP过滤、sql语句黑名单、DBA平滑下线DB、从库流量配置、动态加载配置项项目的Github地址是[https://github.com/Meituan-Dianping/DBProxy](https://github.com/Meituan-Dianping/DBProxy)7>sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据库分库分表访问。Sharding-JDBC是继dubbox和elastic-job之后,ddframe系列开源的第3个项目。Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:* 可适用于任何基于Java的ORM框架,如JPA、Hibernate、Mybatis、Spring JDBC Template或直接使用JDBC。
* 可基于任何第三方的数据库连接池,如DBCP、C3P0、 BoneCP、Druid等。
* 理论上可支持任意实现JDBC规范的数据库。虽然目前仅支持MySQL,但已有支持Oracle、SQLServer等数据库的计划。Sharding-JDBC定位为轻量Java框架,使用客户端直连数据库,以jar包形式提供服务,无proxy代理层,无需额外部署,无其他依赖,DBA也无需改变原有的运维方式。Sharding-JDBC分片策略灵活,可支持等号、between、in等多维度分片,也可支持多分片键。SQL解析功能完善,支持聚合、分组、排序、limit、or等查询,并支持Binding Table以及笛卡尔积表查询。
5、mycat的调研。。
http://www.mycat.io/
具体不多做评价了 这个中间件确实是厉害。
6、Sharding-JDBC的调研
最后 选择了Sharding-JDBC。为啥不选mycat 我也想用啊 不太敢。怕万一哪天就商业化了。
最终 Sharding-JDBC 其实可以满足基本的需要 量级也比较轻
7、Sharding-JDBC DEMO
源码地址
https://github.com/LH-0811/sharding-sphere-demo
准备两个数据库
image.png
这里为了做一些测试 在db1中添加一个分数表
/*Navicat Premium Data TransferSource Server : 192.168.199.127_3316Source Server Type : MySQLSource Server Version : 50724Source Host : 192.168.199.127:3316Source Schema : db0Target Server Type : MySQLTarget Server Version : 50724File Encoding : 65001Date: 01/06/2019 10:17:49
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for user_0
-- ----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (`id` int(11) NOT NULL,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` (`id` int(11) NOT NULL,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for score
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (`id` int(11) NOT NULL,`user_id` int(11) NOT NULL,`score` int(11) NOT NULL DEFAULT '0',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;-- ----------------------------
-- Table structure for user_0
-- ----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (`id` int(11) NOT NULL,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` (`id` int(11) NOT NULL,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
创建一个springboot程序 然后修改配置文件
,这个配置文件的来源是https://mp.weixin.qq.com/s/M0e5u8V_c2sv6aYJHl0Y6Q
# 数据源 db0,db1
sharding.jdbc.datasource.names=db0,db1
# 第一个数据库
sharding.jdbc.datasource.db0.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.db0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.db0.jdbc-url=jdbc:mysql://192.168.199.127:3316/db0?characterEncoding=utf-8
sharding.jdbc.datasource.db0.username=root
sharding.jdbc.datasource.db0.password=123456# 第二个数据库
sharding.jdbc.datasource.db1.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.db1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.db1.jdbc-url=jdbc:mysql://192.168.199.127:3326/db1?characterEncoding=utf-8
sharding.jdbc.datasource.db1.username=root
sharding.jdbc.datasource.db1.password=123456# 水平拆分的数据库(表) 配置分库 + 分表策略 行表达式分片策略
# 分库策略
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=db$->{id % 2}# 分表策略 其中user为逻辑表 分表主要取决于age行
sharding.jdbc.config.sharding.tables.user.actual-data-nodes=db$->{0..1}.user_$->{0..1}
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=age
# 分片算法表达式
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{age % 2}sharding.jdbc.config.sharding.tables.score.actual-data-nodes=db1.score# 主键 UUID 18位数 如果是分布式还要进行一个设置 防止主键重复
#sharding.jdbc.config.sharding.tables.user.key-generator-column-name=id# 打印执行的数据库以及语句
sharding.jdbc.config.props..sql.show=true
spring.main.allow-bean-definition-overriding=true
这边的配置文件 几个注意的地方
分库配置
# 水平拆分的数据库(表) 配置分库 + 分表策略 行表达式分片策略
# 分库策略 指定分库的因子 这里使用id来分库
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
# 这里是通过id来计算 应该操作那个数据库
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=db$->{id % 2}
分表配置
# 分表策略 其中user为逻辑表 分表主要取决于age行#这里是在分库的基础上 添加了分表
#sharding.jdbc.config.sharding.tables.user 是指定逻辑表user 对应的物理表 在那个数据库中的那几张表
sharding.jdbc.config.sharding.tables.user.actual-data-nodes=db$->{0..1}.user_$->{0..1}# 这里是指定user表的分表 是通过那个因子来计算
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=age
# 分片算法表达式
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{age % 2}
# 如果不指定逻辑表 score 对应在db1中的score sharding.jdbc中间件会默认找db0 db1 中的score 但是db0中并没有创建这个表 所以这里就指定他 不找db0中的表
sharding.jdbc.config.sharding.tables.score.actual-data-nodes=db1.score
这里贴一下pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.lh.sharding-sphere</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>sharding-sphere-demo</name><description>sharding-sphere jdbc 分库分表测试demo</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>2.1.5</version></dependency><!-- for spring boot --><dependency><groupId>io.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>3.1.0</version></dependency><!-- for spring namespace --><dependency><groupId>io.shardingsphere</groupId><artifactId>sharding-jdbc-spring-namespace</artifactId><version>3.1.0</version></dependency><!--shardingsphere end--><!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.10</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
Model
@Data
@Table(name = "user")
@NoArgsConstructor
@AllArgsConstructor
public class User {@Id@KeySql(useGeneratedKeys = true)private Integer id;private String name;private Integer age;}
@Data
@Table(name = "score")
@NoArgsConstructor
@AllArgsConstructor
public class Score {@Id@KeySql(useGeneratedKeys = true)private Integer id;private Integer userId;private Integer score;}
Dao
package com.lh.shardingsphere.demo.dao;import com.lh.shardingsphere.demo.model.Score;
import tk.mybatis.mapper.common.BaseMapper;
import tk.mybatis.mapper.common.ExampleMapper;public interface ScoreDao extends BaseMapper<Score>, ExampleMapper<Score> {
}
package com.lh.shardingsphere.demo.dao;import com.lh.shardingsphere.demo.model.User;
import com.lh.shardingsphere.demo.vo.UserScoreVo;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.BaseMapper;
import tk.mybatis.mapper.common.ExampleMapper;public interface UserDao extends BaseMapper<User>, ExampleMapper<User> {// 这是个反面的错误!!。。本来一条sql就只能在一个session中执行,
// 只有在两张表在同一个数据库中存在的时候才可以通过join的方式来获取数据
//
// @Select("SELECT \n" +
// "u.id as userId,\n" +
// "s.id as scoreId,\n" +
// "u.name as name,\n" +
// "s.score as score\n" +
// "FROM \n" +
// "user u \n" +
// "LEFT JOIN \n" +
// "score s \n" +
// "ON u.id = s.user_id \n" +
// "WHERE u.id = ${userId}")@Select("SELECT \n" +"u.id as userId,\n" +"s.id as scoreId,\n" +"u.name as name,\n" +"s.score as score\n" +"FROM\n" +"user_0 u,score s\n" +"WHERE u.id = s.user_id AND u.id = ${userId}")UserScoreVo selectScoreByUserId(@Param("userId") Integer userId);
}
Service
package com.lh.shardingsphere.demo.service;import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lh.shardingsphere.demo.dao.ScoreDao;
import com.lh.shardingsphere.demo.dao.UserDao;
import com.lh.shardingsphere.demo.model.Score;
import com.lh.shardingsphere.demo.model.User;
import com.lh.shardingsphere.demo.vo.UserScoreVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;import java.util.List;@Service
public class UserService {@Autowiredprivate UserDao userDao;@Autowiredprivate ScoreDao scoreDao;public void insertUser(User user) {userDao.insert(user);}public User selectUserById(Integer userId) {return userDao.selectByPrimaryKey(userId);}public List<User> selectUserList() {Example example = new Example(User.class);example.setOrderByClause(" id asc ");return userDao.selectByExample(example);}public List<User> selectByIdAndAge(Integer id, Integer age) {User user = new User();user.setAge(age);user.setId(id);return userDao.select(user);}public List<User> selectByAge(Integer age) {User user = new User();user.setAge(age);return userDao.select(user);}public List<User> selectByName(String name) {User user = new User();user.setName(name);return userDao.select(user);}public User selectByOneName(String name) {User user = new User();user.setName(name);return userDao.selectOne(user);}public List<User> selectByUser(User user) {return userDao.select(user);}public PageInfo<User> pageUser(Integer pageNum, Integer pageSize) {PageHelper.startPage(pageNum, pageSize);Example example = new Example(User.class);example.setOrderByClause(" id asc ");example.createCriteria().andLike("name", "%1%");List<User> users = userDao.selectByExample(example);PageInfo<User> pageInfo = new PageInfo<>(users);PageHelper.clearPage();return pageInfo;}public UserScoreVo selectUserScoreByUserId(Integer userId) {User user = userDao.selectByPrimaryKey(userId);if (user != null) {Score score = new Score();score.setUserId(userId);Score score1 = scoreDao.selectOne(score);UserScoreVo userScoreVo = new UserScoreVo();userScoreVo.setUserId(user.getId());userScoreVo.setScoreId(score1.getId());userScoreVo.setName(user.getName());userScoreVo.setScore(score1.getScore());return userScoreVo;} else {return null;}}public List<Score> getUserScore(Integer userId) {Score score = new Score();score.setUserId(userId);return scoreDao.select(score);}
}
8、demo的测试
package com.lh.shardingsphere.demo.service;import com.github.pagehelper.PageInfo;
import com.lh.shardingsphere.demo.dao.ScoreDao;
import com.lh.shardingsphere.demo.dao.UserDao;
import com.lh.shardingsphere.demo.model.Score;
import com.lh.shardingsphere.demo.model.User;
import com.lh.shardingsphere.demo.vo.UserScoreVo;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService userService;@Autowiredprivate UserDao userDao;@Autowiredprivate ScoreDao scoreDao;// 插入 方法。通过打印的sql执行日志 可以看出// id为基数 分配得到 db1 偶数分配到 db0// user 中 age 奇数分配到 user_1 偶数分配到user_0@Testpublic void insertUser() {for (int i = 1; i < 50;i++){User user = new User(i,"test"+i,i+11);userService.insertUser(user);}for (int i = 50; i < 100;i++){User user = new User(i,"test"+i,i+10);userService.insertUser(user);}}// 通过id查询数据 这里也是通过id 确定了数据库@Testpublic void selectUserById() {User user1 = userService.selectUserById(11);log.info(user1.toString());User user2 = userService.selectUserById(12);log.info(user2.toString());}// 查询列表 这里是每个数据库中每个表返回值的集合// 从结果看出 排序是生效的@Testpublic void selectUserList() {List<User> users = userService.selectUserList();log.info(users.toString());}// 这里通过 age确定了 是哪张表 但是不确定库 所以两个库都执行了@Testpublic void selectByAge(){List<User> users = userService.selectByAge(12);log.info(users.toString());List<User> users1 = userService.selectByAge(13);log.info(users1.toString());}//这里通过 id和age 确定了 库和表 所以就@Testpublic void selectByIdAndAge(){List<User> users = userService.selectByIdAndAge(1, 12);log.info(users.toString());}//这里 因为没有指定 id 和 age 所以 是每个库的每个表中搜索结果的集合@Testpublic void selectByName(){List<User> test33 = userService.selectByName("test33");log.info(test33.toString());}//这里 如果在数据库中每张表的数据不重复的情况下 可以正常执行//如果 任意两个表中 通过都可以通过name获取到数据 就会报错 跟不分库时一样@Testpublic void selectByOneName(){User user = userService.selectByOneName("test33");log.info(user.toString());}// 这里分页正常进行 条件查询正常进行@Testpublic void pageUser(){PageInfo<User> pageInfo = userService.pageUser(1, 10);for (User user : pageInfo.getList()) {log.info(user.getId()+"");}log.info(pageInfo.toString());}@Testpublic void selectUserScoreByUserId() {
// UserScoreVo userScoreVo1 = userService.selectUserScoreByUserId(1);
// log.info(userScoreVo1.toString());UserScoreVo userScoreVo2 = userService.selectUserScoreByUserId(2);log.info(userScoreVo2.toString());}@Testpublic void selectScoreByUserId(){List<Score> userScore = userService.getUserScore(1);log.info(userScore.toString());}//这里的事务在数据库中正常进行 如果抛出异常 数据会回滚数据,即使是不在一个数据库中也会分别进行@Test@Transactional(rollbackFor = Exception.class)public void testSingleTableTransactional() throws Exception{User user = new User(1,"test111111",2222);userDao.updateByPrimaryKey(user);throw new Exception("异常");}@Test@Transactional(rollbackFor = Exception.class)public void testTwoTableTransactional() throws Exception{User user = new User(2,"test111111",2222);userDao.updateByPrimaryKey(user);Score score = new Score();score.setUserId(1);score.setId(1);score.setScore(10000);scoreDao.updateByPrimaryKey(score);throw new Exception("异常");}
}
分库分表:Sharding-JDBC,mycat相关推荐
- 数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量...
当团队对系统业务和数据库进行了细致的梳理,确定了切分方案后,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产 品可供参考,同时很多团队也会选择自主开发实现,而不管是 ...
- 分库分表Sharding
分库分表Sharding 前言 什么是分库分表? 使用场景 分库分表的复杂性 技术选型 demo 笔者个人博客 https://www.yuque.com/yinhe-dglmu 前言 笔者学年尚浅, ...
- Linux+MySQL+MyCat实现分库分表,通过MyCat数据库中间件实现分库分表配置实战
目录 前言 Linux+MySQL+MyCat实现读写分离,主从同步的解决方案 一.Linux下MySQL数据库服务的安装与部署 二.下载Linux MyCat 三.上传Linux服务器,并解压 四. ...
- 数据库分库分表(sharding)系列
数据库分库分表(sharding)系列 转载于:https://www.cnblogs.com/gotodsp/p/6517478.html
- 转数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示
本文原文连接: http://blog.csdn.net/bluishglc/article/details/7696085 ,转载请注明出处!本文着重介绍sharding切分策略,如果你对数据库sh ...
- 数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案...
为什么80%的码农都做不了架构师?>>> 版权声明:本文由本人撰写并发表于2012年9月份的<程序员>杂志,原文题目<一种支持自由规划的Sharding扩容方 ...
- mysql 分库分表中间件 mycat_阿里开源的分布式分库分表中间件之MyCat从入门到放弃...
原标题:阿里开源的分布式分库分表中间件之MyCat从入门到放弃 1.非分片字段查询 Mycat中的路由结果是通过分片字段和分片方法来确定的.例如下图中的一个Mycat分库方案: 根据 tt_waybi ...
- 数据库分库分表(sharding)系列(四) 多数据源的事务处理
系统经sharding改造之后,原来单一的数据库会演变成多个数据库,如何确保多数据源同时操作的原子性和一致性是不得不考虑的一个问题.总体上看,目前对于一个分布式系统的事务处理有三种方式:分布式事务.基 ...
- oracle分库分表原理_02. MyCat 的原理,应用场景,分库分表的思想
# MyCAT 作用是能够代替昂贵的oracle的MySQL集群中间件. 1) 一个彻底开源的,面向企业应用开发的"大数据库集群" 2) 支持事务.ACID.可以替代Mysql的加 ...
- 高可用Mysql架构_Mysql主从复制、Mysql双主热备、Mysql双主双从、Mysql读写分离(Mycat中间件)、Mysql分库分表架构(Mycat中间件)的演变...
[Mysql主从复制] 解决的问题 数据分布:比如一共150台机器,分别往电信.网通.移动各放50台,这样无论在哪个网络访问都很快.其次按照地域,比如国内国外,北方南方,这样地域性访问解决了. 负载均 ...
最新文章
- BZOJ 4059: [Cerc2012]Non-boring sequences ( )
- vue中的浏览量_vue中前进刷新、后退缓存用户浏览数据和浏览位置的实践
- 2017《时间的朋友》思维导图(脑图整理版)
- DatePicker 和 DatePickerDialog的基本使用方法
- Spark(Core)
- 安装新版xampp后apache无法启动提示:Apache Service detected with wrong path解决方案
- 否认气候变暖的人都是睁眼说瞎话
- QT TCP网络编程
- 如何让程序员更容易的开发Web界面?重构SmartAdmin展示TinyUI框架
- java万年历 for_java万年历
- VGA、HDMI、DVI 和 DP接口
- 单片机复位电路基础知识解析
- 带蒙版的安卓剪辑软件_手机上有哪些好用的视频剪辑 App?
- 【转载】HTTPS那些事(图文版)-Network Tips
- Context-Aware Patch Generation for Better Automated Program Repair -上下文感知补丁生成更好的自动化程序修复
- 企业工商数据-------大数据时代下的营销利器
- C语言开发过程中段错误处理方法之经典
- 小虎电商浏览器:拼多多层级有什么作用?多多参谋客服为你解答
- vue 报错avoid mutating a prop directly since the value will be overwritten whenever
- 信道建模(大尺度、小尺度、莱斯衰落、瑞利衰落、莱斯信道、瑞利信道)