根据您提供的信息,有几个可能导致分表操作不生效的原因:

  1. 配置错误:请确保您的 sharding-jdbc 配置文件中的分表规则和分表策略配置正确,并且与代码中的分表规则和策略一致。

  2. 逻辑错误:请确保您的查询语句中使用了正确的分表键,并且查询的时间范围在分表规则的范围内。

  3. 数据源选择错误:请确保您的数据源选择正确,即在动态数据源配置中选择了正确的数据源。

  4. 分表算法错误:请确保您自定义的分表算法实现类中的逻辑正确,并且返回了正确的分表表名。

建议您按照上述步骤逐一检查,查找可能的错误原因。如果问题仍然存在,请提供更详细的错误信息和日志,以便更好地帮助您解决问题。

代码示例

yml 配置

  shardingsphere:
    # 是否启用sharding
    enabled: true
    props:
        sql.show: true
    datasource:
        names: sharding
        # 分库数据源
        sharding:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://222.190.41.66:30001/lyg_vehicle?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
            username: root
            password: aaX9AEx2Gu1M/8pM6EvC+qvtXX0D3i7XJ+9oPCU3rA1D/wNFlCcOgbmKcBlaImBnMv58Hw4Sq+tqG6IJREHjpQ==
    # 分片规则
    sharding:
        tables:
            # 表名
            lyg_tsvol:
                actual-data-nodes: sharding.lyg_tsvol$->{2023..2024}0$->{1..9},sharding.lyg_tsvol$->{2022..2024}1$->{0..2} # 相当于lyg_tsvol_202301->lyg_tsvol_202412
                table-strategy: # 分表策略
                    standard: # 标准分表策略
                        sharding-column: createtime                        # 分表列名
                        preciseAlgorithmClassName: com.itssky.modules.common.core.config.MyPreciseShardingAlgorithm     # 精准的分片算法
                        RangeShardingAlgorithm: com.itssky.modules.common.core.config.MyRangeShardingAlgorithm    # 范围分片算法
            # 表名
            lyg_vehicle:
                actual-data-nodes: sharding.lyg_vehicle_$->{2023..2024}0$->{1..9},ds.t_log_$->{2022..2024}1$->{0..2} # 相当于lyg_vehicle_202301->lyg_vehicle_202412
                table-strategy: # 分表策略
                    standard: # 标准分表策略
                        sharding-column: createtime                        # 分表列名
                        preciseAlgorithmClassName: com.itssky.modules.common.core.config.MyPreciseShardingAlgorithm    # 精准的分片算法
                        RangeShardingAlgorithm: com.itssky.modules.common.core.config.MyRangeShardingAlgorithm    # 范围分片算法

分片规则

public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Timestamp> {

    private String tableNamePrefix;

    public MyPreciseShardingAlgorithm(String tableNamePrefix) {
        this.tableNamePrefix = tableNamePrefix;
    }

    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Timestamp> shardingValue) {
        // 获取年份和月份
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(shardingValue.getValue());
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;

        // 构造表名
        String tableName = tableNamePrefix + year + String.format('%02d', month);

        // 如果这个表名存在于可用的目标表名中,那么返回这个表名
        if (availableTargetNames.contains(tableName)) {
            return tableName;
        }

        // 否则,抛出一个异常
        throw new UnsupportedOperationException('未找到匹配的数据表: ' + tableName);
    }

}

public class MyRangeShardingAlgorithm implements RangeShardingAlgorithm<Timestamp> {
    @Override
    public Collection<String> doSharding(Collection<String> collection,
                                         RangeShardingValue<Timestamp> rangeShardingValue) {
        Range<Timestamp> valueRange = rangeShardingValue.getValueRange();
        Date lowerEnd = valueRange.lowerEndpoint();
        Date upperEnd = valueRange.upperEndpoint();
        log.info('范围分片开始时间:{},结束时间:{}',lowerEnd,upperEnd);
        Set<String> routTables = new HashSet<>();
        if (lowerEnd != null && upperEnd != null) {
            List<String> rangeNameList = getTableNames(lowerEnd, upperEnd);
            for (String string : rangeNameList) {
                //这里的表名是逻辑表名+年月
                routTables.add(rangeShardingValue.getLogicTableName() + string);
            }
        }
        log.info('范围分片表名为:{}',routTables.toString());
        return routTables;

    }


    /**
     * 根据开始时间和结束时间获取表名
     * @param start
     * @param end
     * @return
     */
    private static List<String> getTableNames(Date start, Date end) {
        List<String> result = Lists.newArrayList();
        // 定义日期实例
        Calendar calendar = Calendar.getInstance();
        // 设置日期起始时间
        calendar.setTime(start);
        // 判断是否到结束日期
        while (calendar.getTime().before(end)) {
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH) + 1; // Calendar.MONTH 是从0开始的,所以需要加1
            String yearMonth = String.format('%d%02d', year, month); // 格式化为年月,例如202308或者202411
            result.add(yearMonth);
            // 进行当前日期月份加1
            calendar.add(Calendar.MONTH, 1);
        }
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(end);
        if (calendar.get(Calendar.MONTH)==endCalendar.get(Calendar.MONTH)){
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH) + 1;
            String yearMonth = String.format('%d%02d', year, month);
            result.add(yearMonth);
        }
        return result;
    }

}

sharding_jdbc 配置信息

private TableRuleConfiguration createTableRule(String tableName) {
    // 获取当前日期
    LocalDate currentDate = LocalDate.now();
    int currentYear = currentDate.getYear();
    int currentMonth = currentDate.getMonthValue();

    // 表规则配置
    TableRuleConfiguration tableRuleConfig = new TableRuleConfiguration(tableName, tableName + '$->{2023..' + currentYear + '}0$->{6..' + currentMonth + '}');
    // 配置分表策略
    tableRuleConfig.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration('createtime', new MyPreciseShardingAlgorithm(tableName)));
    // 分布式主键
    tableRuleConfig.setKeyGeneratorConfig(new KeyGeneratorConfiguration('SNOWFLAKE', 'ID'));

    return tableRuleConfig;
}

/**
 * 系统参数配置
 */
private Properties getProperties() {
    Properties shardingProperties = new Properties();
    shardingProperties.put('sql.show', true);
    return shardingProperties;
}

多数据源配置:DruidConfig

@Bean(name = 'dynamicDataSource')
@Primary
public DynamicDataSource dataSource(DataSource masterDataSource)
{
    Map<Object, Object> targetDataSources = new HashMap<>();
    targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
    setDataSource(targetDataSources, DataSourceType.SLAVE.name(), 'slaveDataSource');
    setDataSource(targetDataSources, DataSourceType.SHARDING.name(), 'shardingDataSource');
    return new DynamicDataSource(masterDataSource, targetDataSources);
}

问题排查

  1. 确保您的代码中使用了正确的分表键 createtime,并且查询的时间范围在分表规则的范围内。
  2. 确认您的数据源选择正确,即在动态数据源配置中选择了 shardingDataSource
  3. MyRangeShardingAlgorithm 文件中打断点,观察是否能进入该算法,并检查算法逻辑是否正确。
  4. 查看您的 SQL 查询语句,确认是否使用了 lyg_tsvol 逻辑表名,而不是具体的分表名。
  5. 检查 MyPreciseShardingAlgorithmMyRangeShardingAlgorithm 的实现类,确保逻辑正确,并且返回了正确的分表表名。

如果问题仍然存在,请提供更详细的错误信息和日志,以便更好地帮助您解决问题。

示例代码

// 插入数据
Timestamp currentTime = new Timestamp(System.currentTimeMillis());
LygTsvol tsvol = new LygTsvol();
tsvol.setCreatetime(currentTime);
// 使用 sharding-jdbc 的操作类进行插入
// ...

// 查询数据
// 使用 sharding-jdbc 的操作类进行查询
List<LygTsvol> tsvolList =  // ...

// 获取所有分表名
Collection<String> tableNames = shardingRule.getTableRule(lyg_tsvol).getActualDataNodes();

// 打印所有分表名
System.out.println(tableNames);

// 查询指定时间范围的数据
Timestamp startTime = new Timestamp(System.currentTimeMillis() - 24 * 60 * 60 * 1000); // 昨天
Timestamp endTime = new Timestamp(System.currentTimeMillis()); // 今天
List<LygTsvol> tsvolList =  // ...

总结

本文介绍了 sharding-jdbc 分表操作不生效的常见原因和解决方法,通过逐步排查,可以有效地解决分表问题。在实际应用中,还需要根据具体的业务场景进行调整和优化。

Sharding-JDBC 分表操作不生效的解决方法

原文地址: https://www.cveoy.top/t/topic/qrym 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录