1、使用 shardingsphere 动态创建刷新节点
(这个方式 在最新5.3以上的版本已经不支持自定义动态刷新actualDataNodes节点了。
,但是我又不想一次创建所有表(说不定什么时候就会修改表结构)那么该怎么搞呢,我这里提供一个曲线方案。
2、任务创建下一年的表。
原始表用来复制创建

任务类
/**
* 开启拉取任务(Bean模式)以年为单位创建 每年最后一天创建下一年的表
*/
@XxlJob("createMessageTableJobHandler")
public void createMessageTableJobHandler() throws Exception {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy");
String s = format.format(date);
// 创建下一年的表
Integer data = Integer.parseInt(s) + 1;
// 一次性创建连续两年的表
for (MessageCreatTableEnum value : MessageCreatTableEnum.values()) {
StringBuffer name1 = new StringBuffer(value.getCode() + StringPool.UNDERSCORE + data) ;
StringBuffer name2= new StringBuffer(value.getCode() + StringPool.UNDERSCORE + (data+1)) ;
createTable(value, name1.toString(),name2.toString());
}
System.out.println(1);
}
/**
* 创建指定年的分片
* @param value
* @param table
* @param tableNext
*/
private void createTable(MessageCreatTableEnum value, String table, String tableNext){
try {
Connection connection = dataSource.getConnection();
Statement st = connection.createStatement();
st.setQueryTimeout(10);
// 使用st.execute 会卡死 st.executeUpdate 虽然会报错 但是他会执行创建表sql 不影响功能
st.executeUpdate("CREATE TABLE IF NOT EXISTS `" + table + "` LIKE `" + value.getCode() + "`;" +
"CREATE TABLE IF NOT EXISTS `" + tableNext + "` LIKE `" + value.getCode() + "`;");
} catch (SQLException e) {
log.error(">>>>>>>>>> 这里本来就会抛异常 但是不影响 创建sql执行:{}", e.getMessage(), e);
}
}

3、sharding-jdbc-dev.yaml 配置
dataSources: master: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.cj.jdbc.Driver jdbcUrl: jdbc:mysql://127.0.0.1:3306/sms?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false username: root password: 123456 connectionTimeout: 30000 idleTimeout: 600000 maxLifetime: 1800000 maximumPoolSize: 10 minimumIdle: 5 rules: ### 数据库读写分离配置 - !READWRITE_SPLITTING dataSourceGroups: ### 读写数据库别名 master_ds: writeDataSourceName: master readDataSourceNames: - master transactionalReadQueryStrategy: PRIMARY loadBalancerName: random #负载均衡算法轮询 loadBalancers: random: type: RANDOM #单表配置 - !SINGLE tables: - master_ds.* defaultDataSource: master_ds
- !SHARDING tables: message_data: actualDataNodes: master_ds.message_data_$->{2025..2100} tableStrategy: standard: shardingColumn: create_time shardingAlgorithmName: message_data_year shardingAlgorithms: message_data_year: type: INTERVAL props: datetime-pattern: "yyyy-MM-dd HH:mm:ss" ## 设置分片开始时间 datetime-lower: "2025-01-01 00:00:00" ## 设置分片结束时间 datetime-upper: "2100-12-31 23:59:59" sharding-suffix-pattern: "yyyy" datetime-interval-amount: 1 datetime-interval-unit: YEARS
props: sql-show: true

4、如何命中分片测试(关键点)
由于我们超前配置了分片表(到2100年)但是数据库并没有生成这个些表。每次操作如果没有命中分片字段策略,会检索所有表,报异常。
所以在每次保存 查询操作的时候一定要传递(create_time)字段值。
用来命中分片规则,如果不传递会默认查询原始表。
以mybatis为例
保存必须床底分片字段

查询 设置分片范围 比如id查询为例 除了传递id 还要传递时间 用来命中指定分片。
如果懒可以,直接 lt 当前时间(这个会查询比当前时间小的所有表,查询多次库,性能差点)
