当前位置: 首页 > news >正文

SpringBoot3+ShardingJdbc实现数据分片

文章目录

  • 1.数据分片
    • 1.1 实验说明
    • 1.1 准备数据库环境
    • 1.2 添加依赖,修改pom.xml
    • 1.3 修改application.properties
    • 1.4添加相关类
    • 1.5 添加测试类
    • 1.6 验证插入数据是否会出现有分片:
    • 1.7 验证基于分片ID的查询功能
    • 1.8 验证分片后的范围查询功能
    • 1.9 验证分片后的全表查询功能
    • 1.10 验证非分片表查询功能
  • 2.读写分离

1.数据分片

1.1 实验说明

我们需要实现或者验证以下情况:

  • 我们要模拟 course表中cid字段值为偶数时,数据存 shardingdb1的course1;cid字段值为奇数时,数据存 shardingdb2的course2

  • 并且在ShardingJdbc环境下,如果我们想读普通表(非分片表),此时应该怎么做?

1.1 准备数据库环境

主机IP数据库名称表名类型
192.168.25.91shardingdb1course1分片表
192.168.25.91shardingdb1course2分片表(实际上不会存数据,但又不得不建)
192.168.25.91shardingdb1plain_taable普通表(非分片表)
192.168.25.92shardingdb2course1分片表(实际上不会存数据,但又不得不建)
192.168.25.92shardingdb2course1分片表

建表语句如下:

CREATE TABLE `course1` (`cid` bigint NOT NULL,`cname` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,`user_id` bigint NOT NULL,`cstatus` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,PRIMARY KEY (`cid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;CREATE TABLE `course2` (`cid` bigint NOT NULL,`cname` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,`user_id` bigint NOT NULL,`cstatus` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,PRIMARY KEY (`cid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;CREATE TABLE `plain_table` (`id` bigint NOT NULL,`name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

具体结构如下:
在这里插入图片描述
:这里course为什么要建4张表呢?两张表行不行?只保留shardingdb1.course1和shardingdb1.course2 ? 答案是不行,因为用户SQL没有使用到分片键时(如select * from couse),此时由于shardingjdbc不知道你的shardingdb1.course2表以及shardingdb2.course1表没有数据,故而此时shardingjdbc会查询这四张表,如果不只建两张表,那么后续在例如select * from couse的时候,会爆表不存在的错误。 当然,你也可以选择不同分片表放在同一个数据库实例+同一个数据库名下,此时就只需保留2个表,无需建4个表了。

1.2 添加依赖,修改pom.xml

<properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>3.1.3</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.20</version></dependency><!-- mysql连接驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency><!-- mybatisplus依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version></dependency><!-- shardingJDBC核⼼依赖 --><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.2.1</version><exclusions><exclusion><artifactId>snakeyaml</artifactId><groupId>org.yaml</groupId></exclusion></exclusions></dependency><!-- 版本冲突 --><dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>1.33</version></dependency><!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.38</version></dependency></dependencies>

1.3 修改application.properties

完整内容如下:

# 打印SQL
spring.shardingsphere.props.sql-show = true
spring.main.allow-bean-definition-overriding = true
# ----------------数据源配置
# 让逻辑库和物理库进行关联
spring.shardingsphere.datasource.names=m0,m1spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://192.168.25.91:3306/shardingdb1?serverTimezone=UTC
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123456spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://192.168.25.92:3306/shardingdb2?serverTimezone=UTC
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456
#------------------------分布式序列算法配置
# 雪花算法,⽣成Long类型主键。
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.props.worker-id=1
# 指定分布式主键⽣成策略
spring.shardingsphere.rules.sharding.tables.course.key-generate-strategy.column=cid
spring.shardingsphere.rules.sharding.tables.course.key-generate-strategy.key-generator-name=alg_snowflake
#-----------------------配置实际分⽚节点
spring.shardingsphere.rules.sharding.tables.course.actual-data-nodes=m$->{0..1}.course$->{1..2}
#分库策略(MOD方式)
spring.shardingsphere.rules.sharding.tables.course.database-strategy.standard..sharding-column=cid
spring.shardingsphere.rules.sharding.tables.course.database-strategy.standard.sharding-algorithm-name=course_db_algspring.shardingsphere.rules.sharding.sharding-algorithms.course_db_alg.type=MOD
spring.shardingsphere.rules.sharding.sharding-algorithms.course_db_alg.props.sharding-count=2#分表策略
spring.shardingsphere.rules.sharding.tables.course.table-strategy.standard.sharding-column=cid
spring.shardingsphere.rules.sharding.tables.course.table-strategy.standard.sharding-algorithm-name=course_tbl_alg#==========================================分片算法BEGIN:以下两种方式等价===================================================
#==========分片算法方式一(基于INLINE方式:使用表达式来完成切片算法逻辑计算)==========
#spring.shardingsphere.rules.sharding.sharding-algorithms.course_tbl_alg.type=INLINE
#spring.shardingsphere.rules.sharding.sharding-algorithms.course_tbl_alg.props.algorithm-expression=course$->{cid%2+1}
## 让ShardingJdbc支持SQL范围查询(between)
#spring.shardingsphere.rules.sharding.sharding-algorithms.course_tbl_alg.props.allow-range-query-with-inline-sharding=true#==========分片算法方式二(基于类方式:使用自定义类来完成切片算法逻辑计算)==========
spring.shardingsphere.rules.sharding.sharding-algorithms.course_tbl_alg.type=CLASS_BASED
spring.shardingsphere.rules.sharding.sharding-algorithms.course_tbl_alg.props.strategy=STANDARD
spring.shardingsphere.rules.sharding.sharding-algorithms.course_tbl_alg.props.algorithmClassName=com.jxf.sharding.MyModShardingAlgorithm
# 让ShardingJdbc支持SQL范围查询(between)
#spring.shardingsphere.rules.sharding.sharding-algorithms.course_tbl_alg.props.allow-range-query-with-inline-sharding=true#===================================================分片算法END============================================================

1.4添加相关类

在这里插入图片描述

Course.java

package com.jxf.domian;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@TableName("course")
@Data
public class Course {@TableIdprivate Long cid;private String cname;private Long userId;private String cstatus;
}

PlainTable.java

package com.jxf.domian;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** @author jxf* @Description* @date 2025/6/12 14:02**/@Data
@TableName("plain_table")
public class PlainTable {@TableIdprivate Long id;private String name;}CourseMapper.java
```java
package com.jxf.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jxf.domian.Course;
import org.apache.ibatis.annotations.Select;import java.util.List;/*** @author jxf* @Description* @date 2025/6/11 17:28**/
public interface CourseMapper extends BaseMapper<Course> {@Select("select * from course order by cid asc")List<Course>selectAll();}

PlainTableMapper.java

package com.jxf.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jxf.domian.Course;
import com.jxf.domian.PlainTable;
import org.apache.ibatis.annotations.Select;import java.util.List;/*** @author jxf* @Description* @date 2025/6/11 17:28**/
public interface PlainTableMapper extends BaseMapper<PlainTable> {@Select("select * from plain_table")List<PlainTable>selectAll();}

CourseService.java

package com.jxf.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.jxf.domian.Course;/*** @author jxf* @Description* @date 2025/6/12 10:03**/
public interface CourseService extends IService<Course> {
}

CourseServiceImpl.java

package com.jxf.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jxf.domian.Course;
import com.jxf.mapper.CourseMapper;
import com.jxf.service.CourseService;
import org.springframework.stereotype.Service;/*** @author jxf* @Description* @date 2025/6/12 10:02**/@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {
}
package com.jxf.sharding;import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;import java.util.Collection;
import java.util.Properties;/*** @author jxf* @Description* @date 2025/6/12 13:27**/
public class MyModShardingAlgorithm implements StandardShardingAlgorithm<Long> {/*** 分片算法* @param allPhysicsTables 所有物理表集合,如[course1,course2]* @param preciseShardingValue:对象内容为:{"logicTableName":"course","columnName":"cid","dataNodeInfo":{"prefix":"course","suffixMinLength":1,"paddingChar":"0"},"value":0}* @return 物理表名*/@Overridepublic String doSharding(Collection<String> allPhysicsTables, PreciseShardingValue<Long> preciseShardingValue) {Long idVal = Long.parseLong(preciseShardingValue.getValue()+"");// 分片算法:模拟分片取余算法(你可以根据你的业务需求,做更复杂的分片算法逻辑)String tableSuffix = idVal % 2 == 0 ?  "1" : "2";return preciseShardingValue.getLogicTableName() + tableSuffix;}@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> rangeShardingValue) {return availableTargetNames;}@Overridepublic Properties getProps() {return null;}@Overridepublic void init(Properties properties) {}
}

Main.java

package com.jxf;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.test.context.junit4.SpringRunner;/*** @author jxf* @Description* @date 2025/6/11 16:41**/
@MapperScan("com.jxf.mapper")
@SpringBootApplication
public class Main {public static void main(String[] args) {SpringApplication.run(Main.class);}
}

1.5 添加测试类

TestShardingJdbc.java

package com.jxf;import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jxf.domian.Course;
import com.jxf.domian.PlainTable;
import com.jxf.mapper.CourseMapper;
import com.jxf.mapper.PlainTableMapper;
import com.jxf.service.CourseService;
import jakarta.annotation.Resource;
import jakarta.annotation.security.RunAs;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.ArrayList;
import java.util.List;/*** @author jxf* @Description* @date 2025/6/11 17:30**/
@SpringBootTest(classes = Main.class)
public class TestShardingJdbc {@Resourceprivate CourseMapper courseMapper;@Resourceprivate CourseService courseService;@Resourceprivate PlainTableMapper plainTableMapper;//    ============================分片表测试=============================================@Testpublic void queryById(){// 只到其中一个分片表进行查询,此时性能好Course course = courseMapper.selectById(1L);System.out.println(course);}@Testpublic void queryAll(){// 会到所有分片表上查询,此时性能差List<Course> courses = courseMapper.selectAll();for (Course course : courses) {System.out.println(course);}}@Testpublic void queryRange(){LambdaQueryWrapper<Course>queryWrapper = new LambdaQueryWrapper(Course.class);// in范围查询时,如果id都在同一个分片时,只会到一个指定分片所在表里面查,此时性能好。
//        queryWrapper.in(Course::getCid, List.of(0, 2));
//        queryWrapper.eq(Course::getCstatus, 1);// 每个分片都会去执行SQL,性能差queryWrapper.between(Course::getCid, 5, 10);List<Course> courses = courseMapper.selectList(queryWrapper);for (Course course : courses) {System.out.println(course);}}@Testpublic void insert(){for (int i = 0; i < 10; i++) {Course course = new Course();course.setCid((long)i);course.setCname("lbw" + i);course.setUserId(IdUtil.getSnowflakeNextId());course.setCstatus("1");courseMapper.insert(course);}}@Testpublic void insertBatch(){List<Course>list = new ArrayList<>();for (int i = 0; i < 10; i++) {Course course = new Course();course.setCid((long)i);course.setCname("lbw" + i);course.setUserId(IdUtil.getSnowflakeNextId());course.setCstatus("1");list.add(course);}boolean isSuc = courseService.saveBatch(list);if(isSuc){System.out.println("数据批量保存成功~");}}@Testpublic void update(){int affectCount = courseMapper.update(null, new LambdaUpdateWrapper<>(Course.class).set(Course::getCstatus, 2));System.out.println(affectCount);}@Testpublic void deleteAll(){courseMapper.delete(new LambdaQueryWrapper<>());}//    ============================普通表(非分片表)测试=============================================/*** 默认只操作M0逻辑库对应的物理库*/@Testpublic void queryPlainAll(){// 默认只操作M0逻辑库对应的物理库List<PlainTable> list = plainTableMapper.selectAll();for (PlainTable plainTable : list) {System.out.println(plainTable);}}}

1.6 验证插入数据是否会出现有分片:

执行测试类的insertBatch方法:
执行日志内容如下:

2025-06-12T15:30:25.882+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.882+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.882+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: INSERT INTO course1  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [0, lbw0, 1933064309693087744, 1]
2025-06-12T15:30:25.884+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.884+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.884+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: INSERT INTO course2  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [1, lbw1, 1933064309693087745, 1]
2025-06-12T15:30:25.885+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.885+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.885+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: INSERT INTO course1  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [2, lbw2, 1933064309693087746, 1]
2025-06-12T15:30:25.885+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.885+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.885+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: INSERT INTO course2  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [3, lbw3, 1933064309693087747, 1]
2025-06-12T15:30:25.886+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.886+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.886+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: INSERT INTO course1  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [4, lbw4, 1933064309693087748, 1]
2025-06-12T15:30:25.887+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.887+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.887+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: INSERT INTO course2  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [5, lbw5, 1933064309693087749, 1]
2025-06-12T15:30:25.888+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.888+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.888+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: INSERT INTO course1  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [6, lbw6, 1933064309693087750, 1]
2025-06-12T15:30:25.888+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.888+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.889+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: INSERT INTO course2  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [7, lbw7, 1933064309693087751, 1]
2025-06-12T15:30:25.889+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.889+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.889+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: INSERT INTO course1  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [8, lbw8, 1933064309693087752, 1]
2025-06-12T15:30:25.890+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO course  ( cid, cname, user_id, cstatus )  VALUES  ( ?, ?, ?, ? )
2025-06-12T15:30:25.890+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLInsertStatement(super=InsertStatement(super=AbstractSQLStatement(parameterCount=4, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), table=SimpleTableSegment(tableName=TableNameSegment(startIndex=12, stopIndex=17, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), insertColumns=Optional[InsertColumnsSegment(startIndex=20, stopIndex=51, columns=[ColumnSegment(startIndex=22, stopIndex=24, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=27, stopIndex=31, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=34, stopIndex=40, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), ColumnSegment(startIndex=43, stopIndex=49, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty)])], insertSelect=Optional.empty, values=[InsertValuesSegment(startIndex=62, stopIndex=75, values=[ParameterMarkerExpressionSegment(startIndex=64, stopIndex=64, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=67, stopIndex=67, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=70, stopIndex=70, parameterMarkerIndex=2, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=73, stopIndex=73, parameterMarkerIndex=3, parameterMarkerType=QUESTION, alias=Optional.empty)])]), setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2025-06-12T15:30:25.890+08:00  INFO 21816 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: INSERT INTO course2  ( cid, cname, user_id, cstatus )  VALUES  (?, ?, ?, ?) ::: [9, lbw9, 1933064309693087753, 1]
数据批量保存成功~

四张表结果如下:


shardingdb1.course1表数据如下:
在这里插入图片描述


shardingdb1.course2表数据如下:
在这里插入图片描述


shardingdb2.course1表数据如下:
在这里插入图片描述


shardingdb2.course2表数据如下:
在这里插入图片描述


至此,可以看得出我们的数据分片是没有问题的。

1.7 验证基于分片ID的查询功能

执行测试类的queryAll方法:
执行日志内容如下:

2025-06-12T15:39:24.820+08:00  INFO 3904 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT cid,cname,user_id,cstatus FROM course WHERE cid=?
2025-06-12T15:39:24.821+08:00  INFO 3904 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(super=SelectStatement(super=AbstractSQLStatement(parameterCount=1, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=55, stopIndex=55, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), projections=ProjectionsSegment(startIndex=7, stopIndex=31, projections=[ColumnProjectionSegment(column=ColumnSegment(startIndex=7, stopIndex=9, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=11, stopIndex=15, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=17, stopIndex=23, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=25, stopIndex=31, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty)], distinctRow=false), from=SimpleTableSegment(tableName=TableNameSegment(startIndex=38, stopIndex=43, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), where=Optional[WhereSegment(startIndex=45, stopIndex=55, expr=BinaryOperationExpression(startIndex=51, stopIndex=55, left=ColumnSegment(startIndex=51, stopIndex=53, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), right=ParameterMarkerExpressionSegment(startIndex=55, stopIndex=55, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), operator==, text=cid=?))], groupBy=Optional.empty, having=Optional.empty, orderBy=Optional.empty, combine=Optional.empty), table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2025-06-12T15:39:24.821+08:00  INFO 3904 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: SELECT cid,cname,user_id,cstatus FROM course2 WHERE cid=? ::: [1]
Course(cid=1, cname=lbw1, userId=1933064309693087745, cstatus=1)

根据上述日志可知,我们shardingjdbc 只有到其中一个分片表上执行查询SQL,性能好。此时你也可以在MyModShardingAlgorithm类上进行打断点,看其分片算法执行过程。

1.8 验证分片后的范围查询功能

执行测试类的queryRange方法:
执行日志内容如下:

2025-06-12T15:45:23.287+08:00  INFO 31564 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT  cid,cname,user_id,cstatus  FROM course      WHERE  (cid BETWEEN ? AND ?)
2025-06-12T15:45:23.287+08:00  INFO 31564 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(super=SelectStatement(super=AbstractSQLStatement(parameterCount=2, parameterMarkerSegments=[ParameterMarkerExpressionSegment(startIndex=72, stopIndex=72, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), ParameterMarkerExpressionSegment(startIndex=78, stopIndex=78, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty)], commentSegments=[]), projections=ProjectionsSegment(startIndex=8, stopIndex=32, projections=[ColumnProjectionSegment(column=ColumnSegment(startIndex=8, stopIndex=10, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=12, stopIndex=16, identifier=IdentifierValue(value=cname, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=18, stopIndex=24, identifier=IdentifierValue(value=user_id, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty), ColumnProjectionSegment(column=ColumnSegment(startIndex=26, stopIndex=32, identifier=IdentifierValue(value=cstatus, quoteCharacter=NONE), owner=Optional.empty), alias=Optional.empty)], distinctRow=false), from=SimpleTableSegment(tableName=TableNameSegment(startIndex=40, stopIndex=45, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), where=Optional[WhereSegment(startIndex=52, stopIndex=79, expr=BetweenExpression(startIndex=60, stopIndex=78, left=ColumnSegment(startIndex=60, stopIndex=62, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty), betweenExpr=ParameterMarkerExpressionSegment(startIndex=72, stopIndex=72, parameterMarkerIndex=0, parameterMarkerType=QUESTION, alias=Optional.empty), andExpr=ParameterMarkerExpressionSegment(startIndex=78, stopIndex=78, parameterMarkerIndex=1, parameterMarkerType=QUESTION, alias=Optional.empty), not=false))], groupBy=Optional.empty, having=Optional.empty, orderBy=Optional.empty, combine=Optional.empty), table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2025-06-12T15:45:23.287+08:00  INFO 31564 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: SELECT  cid,cname,user_id,cstatus  FROM course1      WHERE  (cid BETWEEN ? AND ?) UNION ALL SELECT  cid,cname,user_id,cstatus  FROM course2      WHERE  (cid BETWEEN ? AND ?) ::: [5, 10, 5, 10]
2025-06-12T15:45:23.287+08:00  INFO 31564 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: SELECT  cid,cname,user_id,cstatus  FROM course1      WHERE  (cid BETWEEN ? AND ?) UNION ALL SELECT  cid,cname,user_id,cstatus  FROM course2      WHERE  (cid BETWEEN ? AND ?) ::: [5, 10, 5, 10]
Course(cid=6, cname=lbw6, userId=1933064309693087750, cstatus=1)
Course(cid=8, cname=lbw8, userId=1933064309693087752, cstatus=1)
Course(cid=5, cname=lbw5, userId=1933064309693087749, cstatus=1)
Course(cid=7, cname=lbw7, userId=1933064309693087751, cstatus=1)
Course(cid=9, cname=lbw9, userId=1933064309693087753, cstatus=1)

根据上面日志可知,当使用between范围查询时,会出现所有分片表执行查询,当你的查询条件可能涉及多个分片时,那么此时查询会变成所有分片表查询。

你可以将查询条件换成 queryWrapper.in(Course::getCid, List.of(0, 2)),此时由于查询条件里面的参数值都是属于同一个分片,此时ShardingJDBC只会到其中一个分片表上进行查询,此时性能高。

你可以再把查询条件换成queryWrapper.in(Course::getCid, List.of(0,1, 2))时,此时ShardingJDBC会到所有分片表上执行查询,此时性能低。

故而,当你分片键 in中的参数值涉及到多个分片时,可以考虑分成多个SQL,把相同属于相同分片的ID放在同一个SQL。

1.9 验证分片后的全表查询功能

执行测试类的queryAll方法:
执行日志内容如下:

2025-06-12T15:36:27.652+08:00  INFO 1968 --- [           main] ShardingSphere-SQL                       : Logic SQL: select * from course order by cid asc
2025-06-12T15:36:27.653+08:00  INFO 1968 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(super=SelectStatement(super=AbstractSQLStatement(parameterCount=0, parameterMarkerSegments=[], commentSegments=[]), projections=ProjectionsSegment(startIndex=7, stopIndex=7, projections=[ShorthandProjectionSegment(startIndex=7, stopIndex=7, owner=Optional.empty, alias=Optional.empty)], distinctRow=false), from=SimpleTableSegment(tableName=TableNameSegment(startIndex=14, stopIndex=19, identifier=IdentifierValue(value=course, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), where=Optional.empty, groupBy=Optional.empty, having=Optional.empty, orderBy=Optional[OrderBySegment(startIndex=21, stopIndex=36, orderByItems=[ColumnOrderByItemSegment(super=TextOrderByItemSegment(), column=ColumnSegment(startIndex=30, stopIndex=32, identifier=IdentifierValue(value=cid, quoteCharacter=NONE), owner=Optional.empty))])], combine=Optional.empty), table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2025-06-12T15:36:27.653+08:00  INFO 1968 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: select * from course1 order by cid asc
2025-06-12T15:36:27.653+08:00  INFO 1968 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: select * from course2 order by cid asc
2025-06-12T15:36:27.653+08:00  INFO 1968 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: select * from course1 order by cid asc
2025-06-12T15:36:27.653+08:00  INFO 1968 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: select * from course2 order by cid asc
Course(cid=0, cname=lbw0, userId=1933064309693087744, cstatus=1)
Course(cid=1, cname=lbw1, userId=1933064309693087745, cstatus=1)
Course(cid=2, cname=lbw2, userId=1933064309693087746, cstatus=1)
Course(cid=3, cname=lbw3, userId=1933064309693087747, cstatus=1)
Course(cid=4, cname=lbw4, userId=1933064309693087748, cstatus=1)
Course(cid=5, cname=lbw5, userId=1933064309693087749, cstatus=1)
Course(cid=6, cname=lbw6, userId=1933064309693087750, cstatus=1)
Course(cid=7, cname=lbw7, userId=1933064309693087751, cstatus=1)
Course(cid=8, cname=lbw8, userId=1933064309693087752, cstatus=1)
Course(cid=9, cname=lbw9, userId=1933064309693087753, cstatus=1)

根据日志上述得知,如果没有用到分片键,那么会出现所有分片表全表查询。

1.10 验证非分片表查询功能

往表里手动插入一条数据:
在这里插入图片描述

执行测试类的queryPlainAll方法:
执行日志内容如下:

025-06-12T15:57:51.488+08:00  INFO 25832 --- [           main] ShardingSphere-SQL                       : Logic SQL: select * from plain_table
2025-06-12T15:57:51.489+08:00  INFO 25832 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(super=SelectStatement(super=AbstractSQLStatement(parameterCount=0, parameterMarkerSegments=[], commentSegments=[]), projections=ProjectionsSegment(startIndex=7, stopIndex=7, projections=[ShorthandProjectionSegment(startIndex=7, stopIndex=7, owner=Optional.empty, alias=Optional.empty)], distinctRow=false), from=SimpleTableSegment(tableName=TableNameSegment(startIndex=14, stopIndex=24, identifier=IdentifierValue(value=plain_table, quoteCharacter=NONE)), owner=Optional.empty, alias=Optional.empty), where=Optional.empty, groupBy=Optional.empty, having=Optional.empty, orderBy=Optional.empty, combine=Optional.empty), table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2025-06-12T15:57:51.489+08:00  INFO 25832 --- [           main] ShardingSphere-SQL                       : Actual SQL: m0 ::: select * from plain_table
PlainTable(id=1, name=lbw)

根据日志上述得知,默认操作的是m0逻辑库关联的物理库。

2.读写分离

读写分离核心配置如下:

#配置读写分离虚拟库,主库一个,从库可以多个
spring.shardingsphere.rules.readwrite-splitting.data-sources.readwrite_ds.static-strategy.write-data-source-name=逻辑主库
spring.shardingsphere.rules.readwrite-splitting.data-sources.readwrite_ds.static-strategy.read-data-source-names[0]=逻辑从库1
spring.shardingsphere.rules.readwrite-splitting.data-sources.readwrite_ds.static-strategy.read-data-source-names[1]=逻辑从库2
#指定负载均衡器
spring.shardingsphere.rules.readwrite-splitting.data-sources.readwrite_ds.load-balancer-name=user_lb#配置负载均衡器
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=ROUND_ROBIN
# 按事务轮训
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=TRANSACTION_ROUND_ROBIN
# 按操作随机
spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=RANDOM
# 按事务随机
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=TRANSACTION_RANDOM
# 读请求全部强制路由到主库
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=FIXED_PRIMARY

相关文章:

  • HarmonyOS运动开发:深度解析文件预览的正确姿势
  • 利用Snowflake与SNP Glue揭示数据集成新潜力
  • ‘Target closed‘ error in Puppeteer解决
  • [前端]HTML模拟实现一个基于摄像头的手势识别交互页面
  • GitLab 拉取变慢的原因及排查方法
  • 【智算中心】以网补算
  • 力扣面试150题--单词接龙
  • React 集中状态管理方案
  • Windows安装docker及使用
  • 操作系统——第五章(I/O设备)
  • [架构之美]深入优化Spring Boot WebFlux应用
  • 机器学习-黑马笔记
  • STM32 开发 - 中断案例(中断概述、STM32 的中断、NVIC 嵌套向量中断控制器、外部中断配置寄存器组、EXTI 外部中断控制器、实例实操)
  • Python中的函数和方法概要
  • 【AS32系列MCU调试教程】硬件调试:JLink 驱动配置与调试技巧
  • MCU、MPU、GPU、Soc、DSP、FPGA、CPLD……它们到底是什么?
  • C# 结构(构造函数和析构函数)
  • BEV和OCC学习-8:mmdet3d 3D分割demo测试
  • stm32f103 标准库移植rt-thread nano
  • Django(自用)
  • 风铃微网站怎么做/app推广平台有哪些
  • 网站目录怎么做外链/网站维护的内容有哪些
  • 做ppt找图片的网站/下列哪些店铺适合交换友情链接
  • 备案网站可以做接码平台么/百度搜索排名优化哪家好
  • 苍南县网站集约化建设/快刷网站
  • 长沙网站建设论坛/关键词分析