ShardingJdbc-分表;分库;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务
创建项目
一顿下一步,勾选web、lombok等插件
分表
导包
ShardingJdbc
官方最新稳定版4.1.1
<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/sharding-jdbc-spring-boot-starter -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
Mysql
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
Druid
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
MyBatisPlus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
表结构
注意:之前我这表名叫table_0,结果一直报找不到表,后来发现,不能用关键字
CREATE TABLE `master_db`.`my_table_0` (
`id` BIGINT (20) NOT NULL,
`source` VARCHAR (20),
`remark` VARCHAR (100),
PRIMARY KEY (`id`)
);
CREATE TABLE `master_db`.`my_table_1` (
`id` BIGINT (20) NOT NULL,
`source` VARCHAR (20),
`remark` VARCHAR (100),
PRIMARY KEY (`id`)
);
Yml
application-sharding_table.yml
server:
port: 80
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db #库名,只是名字
db: #数据源
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片规则
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志
至此配置完毕,运行效果见下方代码
分库
Yml
application-sharding_db.yml
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db1,db2 #库名,只是名字
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db1.my_table
pub_table:
actualDataNodes: db2.pub_table
props:
sql:
show: true #输出日志
Java
Table0Controller.java中新增方法
@GetMapping("saveByShardingDb")
public void saveByShardingDb(){
table0Service.save(new Table0(){{setSource("source");setRemark("remark");}});
pubTableService.save(new PubTable(){{setSource("source");setRemark("remark");}});
}
测试后可看到数据该去哪去哪了
分库分表
java代码都不改,只改数据库及yml
数据库
master_db、 slave_db1、 slave_db2
库中分别创建my_table_0、my_table_1,结构同 上
Yml
application-sharding_master_slave.yml
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2 #库名,只是名字
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
#分库分表start
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db$->{0..2}.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
databaseStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: db$->{id % 3} #分片算法,分了三个库,所以要%3
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
#分库分表end
props:
sql:
show: true #输出日志
然后继续访问第一步的save&select方法就可看到效果了,配置文件中写的主从库没有实际意义,起错名字了,实际都会往里面写
读写分离
数据库
模拟主从,不做MySql真正的主从同步
上面做表分片时已经创建好了主库master_db 再创建两个库 slave_db1 slave_db2
三个库表结构一致
master_db表中无数据
slave_db1 表数据如下
"id" "source" "remark"
"1" "source1" "remark1"
slave_db2 表数据如下
"id" "source" "remark"
"1" "source2" "remark2"
Yml
application-master_slave.yml
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: masterdb,slavedb1,slavedb2 #库名,只是名字
masterdb: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
slavedb1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
slavedb2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
masterslave:
name: dbs
master-data-source-name: masterdb #主库
slave-data-source-names: slavedb1,slavedb2 #多个从库
load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机 ROUND_ROBIN 轮训
props:
sql:
show: true #输出日志
这时,访问上面搭好的项目,即可进行读写分离,代码见上方链接
其他
只请求主库
在请求上方添加如下代码即可
// HintManager hintManager = HintManager.getInstance();
// hintManager.setMasterRouteOnly();
@GetMapping("select")
public PageInfo select(int pageNum,int pageSize,Long id){
// HintManager hintManager = HintManager.getInstance();
// hintManager.setMasterRouteOnly();
PageHelper.startPage(pageNum,pageSize);
QueryWrapper<Table0> queryWrapper=new QueryWrapper();
if(!StringUtils.isEmpty(id)) {
queryWrapper.eq("id", id);
}
List<Table0> list = table0Service.list(queryWrapper);
PageInfo pageInfo = new PageInfo<>(list);
return pageInfo;
}
读写分离判断逻辑代码
大致的流程是shardingJdbc根据sql获得对应的sqlStatement,然后只有SelectStatement的才走从库
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.masterslave.route.engine.impl;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.api.hint.HintManager;
import org.apache.shardingsphere.core.rule.MasterSlaveRule;
import org.apache.shardingsphere.sql.parser.sql.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement;
import java.util.ArrayList;
/**
* Data source router for master-slave.
*/
@RequiredArgsConstructor
public final class MasterSlaveDataSourceRouter {
private final MasterSlaveRule masterSlaveRule;
/**
* Route.
*
* @param sqlStatement SQL statement
* @return data source name
*/
public String route(final SQLStatement sqlStatement) {
if (isMasterRoute(sqlStatement)) {
MasterVisitedManager.setMasterVisited();
return masterSlaveRule.getMasterDataSourceName();
}
return masterSlaveRule.getLoadBalanceAlgorithm().getDataSource(
masterSlaveRule.getName(), masterSlaveRule.getMasterDataSourceName(), new ArrayList<>(masterSlaveRule.getSlaveDataSourceNames()));
}
private boolean isMasterRoute(final SQLStatement sqlStatement) {
return containsLockSegment(sqlStatement) || !(sqlStatement instanceof SelectStatement) || MasterVisitedManager.isMasterVisited() || HintManager.isMasterRouteOnly();
}
private boolean containsLockSegment(final SQLStatement sqlStatement) {
return sqlStatement instanceof SelectStatement && ((SelecStatement) sqlStatement).getLock().isPresent();
}
}
一主多从+分表
上面实现了一主多从和表分片,现在把它整合到一起
java代码还是没改,主要改的还是Yml
Yml
application-sharding_db_table_oneMaster_slaves.yml
关键配置见 masterSlaveRule,分片配置未改
#一主多从+表分片
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2 #库名,只是名字
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
masterSlaveRule: # 这里配置这个规则的话,相当于是全局读写分离配置
name: ds_rw # 名称,合法的字符串即可,但如果涉及到在读写分离的基础上设置分库分表,则名称需要有意义才可以,另外,虽然目前没有强制要求,但主从库配置需要配置在实际关联的主从库上,如果配置的数据源之间主从是断开的状态,那么可能会发生写入的数据对于只读会话无法读取到的问题
# 如果一个会话发生了写入并且没有提交(显式打开事务),sharidng sphere在后续的路由中,select都会在主库执行,直到会话提交
masterDataSourceName: db0 # 主库的DataSource名称
slaveDataSourceNames: # 从库的DataSource列表,至少需要有一个
- db1
- db2
loadBalanceAlgorithmType: ROUND_ROBIN #从库负载均衡算法类型,可选值:ROUND_ROBIN,RANDOM。若loadBalanceAlgorithmClassName存在则忽略该配置,默认为ROUND_ROBIN
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db$->{0..2}.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
databaseStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: db$->{id % 3} #分片算法,分了三个库,所以要%3
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志
一主多从+分库分表
上面实现了一主多从和表分片,现在把它整合到一起
java代码还是没改,主要改的还是Yml
创建了两个主库两个从库master_db1、master_db2、slave_db1、slave_db2
下方配置为 master_db1与slave_db1为主从关系、master_db2与slave_db2为主从关系
修改点有点多,查看标*****的位置
Yml
application-sharding_db_table_masters_slaves.yml
#一主多从+表分片
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2,db3 #库名,只是名字 ******************新增名称db3
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #主库1 ****************** 添加主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db3: #从库2 ******************添加从库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding:
master-slave-rules: # 新增配置 ******************
db0: # 此处名字一定要配置和下面 master-data-source-name 名字一致的
master-data-source-name: db0
slave-data-source-names: db2
db1: # 此处名字一定要配置和下面 master-data-source-name 名字一致的
master-data-source-name: db1
slave-data-source-names: db3
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db$->{0..1}.my_table_$->{0..1} #******************每组有一主一从,所以是0..1
databaseStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: db$->{(id / 10).toBigInteger() % 2} # *******不能再用id%2方式了,会导致数据分配不均,所以需要自定义方法
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志
公共表&数据脱敏
公共表
项目中会有很多字典表、配置表等等,此类表数据固定、量级不大,所以可以无需采用分库分表,每个库存一份;
当配置公共表后,每次对公共表进行操作,都会同步操作所有库中的公共表
数据库
分别在三个库中新增表pub_table
Java代码
生成pub_table相关的MybatisPlus代码
Yml
application-publicTable_encryptor.yml
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2 #库名,只是名字
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding:
default-data-source-name: db #如果有多个库,公共表只有一个库有,那么,就要指定有公共表的库,否则会报找不到表
default-database-strategy:
inline:
sharding-column: id
algorithm-expression: db$->{id % 3}
broadcast-tables: pub_table #公共表配置,可以多个
props:
sql:
show: true #输出日志
数据脱敏
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db #库名,只是名字
db: #数据源
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding: #指定表的分片规则
# 数据脱敏规则配置---start
encrypt-rule:
encryptors:
encryptor_MD5:
type: MD5
props:
md5.key.value: 123456
encryptor_aes:
# 加密、解密器的名字,内置的为MD5,aes.
# 可以自定义,实现
# org.apache.shardingsphere.encrypt.strategy.spi.Encryptor
# 或者
# org.apache.shardingsphere.encrypt.strategy.spi.QueryAssistedEncryptor
# 这两个接口即可
type: aes
props:
aes.key.value: 123456
tables:
# tables
my_table:
columns:
# 逻辑列,就是写SQL里面的列,因为实体类的名字和数据库的加密列一致,所以这里都是name
source:
# 原文列
# plainColumn: password
# 密文列,用来存储密文数据
cipherColumn: source
# 加密器名字
encryptor: encryptor_MD5
# password1:
# 原文列
# plainColumn: password1
# 密文列,用来存储密文数据
# cipherColumn: aes_password
# 加密器名字
# encryptor: encryptor_aes
# 数据脱敏规则配置---end
broadcast-tables: pub_table #公共表
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志
query.with.cipher.column: true #是否使用密文列查询
分布式事务
分库分表后,因为不是一个库了,所以一旦报错,数据无法回滚
Yml
使用上方 application-sharding_db_table_masters_slaves.yml
pom
<!-- 使用 XA 事务时,需要引入此模块 -->
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-transaction-spring-boot-starter</artifactId>
<version>3.1.0</version>
<type>pom</type>
</dependency>
Java
新增
package com.rollback.shardingjdbcdemo.demo.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
@Bean
public PlatformTransactionManager txManager(final DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
修改save方法
saveByTransaction
package com.rollback.shardingjdbcdemo.demo.sharding.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rollback.shardingjdbcdemo.demo.sharding.model.Table0;
import com.rollback.shardingjdbcdemo.demo.sharding.service.Table0Service;
import org.apache.shardingsphere.api.hint.HintManager;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Random;
/**
* <p>
* 前端控制器
* </p>
*
* @author koala
* @since 2021-05-31
*/
@RestController
@RequestMapping("/table0")
public class Table0Controller {
@Autowired
Table0Service table0Service;
@GetMapping("save")
public void save(int tag){
table0Service.save(new Table0(){{setSource("source"+tag);setRemark("remark"+tag);}});
}
@Transactional
@ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
@GetMapping("saveByTransaction")
public void saveByTransaction(int tag){
for (int i = 0; i < 10; i++) {
if(i==5){
List list=null;
list.add("error");
}
table0Service.save(new Table0(){{setSource("source"+tag);setRemark("remark"+tag);}});
}
}
@GetMapping("select")
public PageInfo select(int pageNum,int pageSize,Long id){
// HintManager hintManager = HintManager.getInstance();
// hintManager.setMasterRouteOnly();
PageHelper.startPage(pageNum,pageSize);
QueryWrapper<Table0> queryWrapper=new QueryWrapper();
if(!StringUtils.isEmpty(id)) {
queryWrapper.eq("id", id);
}
queryWrapper.eq("source","source1");
List<Table0> list = table0Service.list(queryWrapper);
PageInfo pageInfo = new PageInfo<>(list);
return pageInfo;
}
@GetMapping("select1")
public List<Table0> select1(int pageNum,int pageSize,Long id){
QueryWrapper<Table0> queryWrapper=new QueryWrapper();
if(!StringUtils.isEmpty(id)) {
queryWrapper.eq("id", id);
}
//queryWrapper.eq("source","source1");
List<Table0> list = table0Service.list(queryWrapper);
return list;
}
}
验证步骤:
清空数据库
执行saveByTransaction
报错后观察数据库,一条都没有
去掉
@Transactional
@ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE后,会出现保存部分数据的情况
异常
如遇到 如下异常,只是一个健康检查的错误,可以通过添加 src/main/java/com/rollback/shardingjdbcdemo/demo/conf/DataSourceHealthConfig.java解决
ConnectionCallback; isValid; nested exception is java.sql.SQLFeatureNotSupportedException: isValid
代码下载
代码见sharding包下,请求入口见 Table0Controller
ShardingJdbc-分表;分库;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务的更多相关文章
- 分库分表(3) ---SpringBoot + ShardingSphere 实现读写分离
分库分表(3)---ShardingSphere实现读写分离 有关ShardingSphere概念前面写了两篇博客: 1.分库分表(1) --- 理论 2. 分库分表(2) --- ShardingS ...
- 分库分表(7)--- SpringBoot+ShardingSphere实现分库分表 + 读写分离
分库分表(7)--- ShardingSphere实现分库分表+读写分离 有关分库分表前面写了六篇博客: 1.分库分表(1) --- 理论 2.分库分表(2) --- ShardingSphere(理 ...
- sharing-jdbc实现读写分离及分库分表
需求: 分库:按业务线business_id将不同业务线的订单存储在不同的数据库上: 分表:按user_id字段将不同用户的订单存储在不同的表上,为方便直接用非分片字段order_id查询,可使用基因 ...
- 分库分表(6)--- SpringBoot+ShardingSphere实现分表+ 读写分离
分库分表(6)--- ShardingSphere实现分表+ 读写分离 有关分库分表前面写了五篇博客: 1.分库分表(1) --- 理论 2.分库分表(2) --- ShardingSphere(理论 ...
- 阿里P8架构师谈:数据库分库分表、读写分离的原理实现,使用场景
本文转载自:阿里P8架构师谈:数据库分库分表.读写分离的原理实现,使用场景 为什么要分库分表和读写分离? 类似淘宝网这样的网站,海量数据的存储和访问成为了系统设计的瓶颈问题,日益增长的业务数据,无疑对 ...
- keeplived+mycat+mysql高可用读写分离水平分表(谁看谁都会)
一:环境准备: 应用 主机 mysql-master 192.168.205.184 mysql-slave 192.168.205.185 mycat-01,keeplived,jdk 192.16 ...
- SpringBoot使用Sharding-JDBC读写分离
本文介绍SpringBoot使用当当Sharding-JDBC进行读写分离. 1.有关Sharding-JDBC 本文还是基于当当网Sharding-Jdbc的依赖,与上一篇使用Sharding-Jd ...
- mycat读写分离
版本:mycat1.0 只需要读写分离的功能,分库分表的都不需要. 涉及到的配置文件: 1.conf/server.xml 主要配置的是mycat的用户名和密码,mycat的用户名和密码和mys ...
- ProxySQL 配置详解及读写分离(+GTID)等功能说明 (完整篇)
ProxySQL是灵活强大的MySQL代理层, 是一个能实实在在用在生产环境的MySQL中间件,可以实现读写分离,支持 Query 路由功能,支持动态指定某个 SQL 进行 cache,支持动态加载配 ...
随机推荐
- 洛谷P5019 [NOIP2018 提高组] 铺设道路
题目描述 春春是一名道路工程师,负责铺设一条长度为 n 的道路. 铺设道路的主要工作是填平下陷的地表.整段道路可以看作是 n 块首尾相连的区域,一开始,第 i 块区域下陷的深度为 di. 春春每天可以 ...
- jQuery EasyUI 的editor组件使用
问题:最近在优化一个项目时,前端用到了 easyui这个插件来实现表格,搞了很久,才实现出一部分功能,但是还是有很多地方不熟悉,故记录一下,以后再研究 第一个实例------------------- ...
- Firewalld工作区
firewalld的字符界面管理工具是 firewall-cmd firewalld默认配置文件有两个:/usr/lib/firewalld/ (系统配置,尽量不要修改)和 /etc/firewal ...
- Docker版本Jenkins的使用
一. 什么是Jenkins Jenkins是当前非常流行的一款持续集成工具,可以帮助大家把更新后的代码自动部署到服务器上运行. 二. 为什么用docker版的Jenkins Jenkins主要有三种安 ...
- 软件版本GA、Beta、RC含义
Alpha:是内部测试版,一般不向外部发布,会有很多Bug.一般只有测试人员使用.Beta:也是测试版,这个阶段的版本会一直加入新的功能.在Alpha版之后推出.RC:(Release Candida ...
- listview界面显示
1.布局写listview 2.找到listview 3.封装新闻数据到list集合中 ,目的是为adapter提供数据展示. 4.封装一个Adapter类继承B ...
- 常用汉字大全:汉字读音表GB2312版(共7809个汉字)
转载请注明来源:https://www.cnblogs.com/hookjc/ 常用汉字:a1:阿啊呵腌吖锕a2:啊呵嗄a3:啊呵a4:啊呵ai1:哀挨埃唉哎捱锿ai2:呆挨癌皑捱ai3:矮哎蔼霭嗳a ...
- ubuntu中codeblocks设置代码黑色主题配色
说明 网上资料较杂乱,特整理以备留用和他人参阅. 配置文件下载 首先下载配置文件,命名为default.conf. 配置文件 官方配置文件网址 将配置文件替换ubuntu如下路径内的default.c ...
- 了解Java格式化输出printf,一篇就够了
格式化详解 格式化输出 转换符 常用转换符 日期转换 搭配标志 了解C语言的都知道,C语言的输出语句printf();可以对里面的内容格式化然后输出.那么在Java中也给我们提供了相关的方法.两者十分 ...
- Solution -「CEOI 2017」「洛谷 P4654」Mousetrap
\(\mathscr{Description}\) Link. 在一个含 \(n\) 个结点的树形迷宫中,迷宫管理者菈米莉丝和一只老鼠博弈.老鼠初始时在结点 \(y\),有且仅有结点 \(x\ ...