数据库分表遇到的问题

本文探讨了数据库分表过程中遇到的问题,如精确度调整、范围划分,以及如何通过自定义算法和分表策略解决。作者分享了如何通过Mybatis插件处理分表查询,以及配置分表规则实例。同时揭示了常见坑点和应对方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库分表遇到的问题

数据库分表的自定方法

分表的表名是表名_年份

处理数据分表精度问题


    @Override
    protected String getShardingTableNameSuffix(Date shardingColumnValue) {
        String yyyyMM = DateUtils.date2String(shardingColumnValue, DateFormatType.SIMPLE_DATE_FORMAT_YEAR_MON);
        String yyyy = yyyyMM.substring(0,4);
        return "_" + yyyy;
    }

处理数据库分表范围问题


    @Override
    protected List<String> getTableNamesLess(Date upper, Collection<String> shardingTableNameList) {
        List<String> result = new ArrayList<>();
        String upperSuffix = DateUtils.date2String(upper, DateFormatType.SIMPLE_DATE_FORMAT_YEAR_MON);
        upperSuffix = upperSuffix.substring(0,4);
        String finalUpperSuffix = upperSuffix;
        shardingTableNameList.forEach(tableName -> {
            String tableSuffix = tableName.substring(tableName.lastIndexOf("_") + 1);
            if (Integer.parseInt(tableSuffix) <= (Integer.parseInt(finalUpperSuffix))) {
                result.add(tableName);
            }
        });
        return result;
    }

    @Override
    protected List<String> getTableNamesGreater(Date lower, Collection<String> shardingTableNameList) {
        List<String> result = new ArrayList<>();
        String lowerSuffix = DateUtils.date2String(lower, DateFormatType.SIMPLE_DATE_FORMAT_YEAR_MON);
        lowerSuffix= lowerSuffix.substring(0,4);
        String finalLowerSuffix = lowerSuffix;
        shardingTableNameList.forEach(tableName -> {
            String tableSuffix = tableName.substring(tableName.lastIndexOf("_") + 1);
            if (Integer.parseInt(tableSuffix) >= (Integer.parseInt(finalLowerSuffix))) {
                result.add(tableName);
            }
        });
        return result;
    }

    @Override
    protected List<String> getTableNamesGreaterAndLess(Date lower, Date upper, Collection<String> shardingTableNameList) {
        List<String> result = new ArrayList<>();
        String lowerSuffix = DateUtils.date2String(lower, DateFormatType.SIMPLE_DATE_FORMAT_YEAR_MON);
        String upperSuffix = DateUtils.date2String(upper, DateFormatType.SIMPLE_DATE_FORMAT_YEAR_MON);
        lowerSuffix= lowerSuffix.substring(0,4);
        upperSuffix = upperSuffix.substring(0,4);
        String finalLowerSuffix = lowerSuffix;
        String finalUpperSuffix = upperSuffix;
        shardingTableNameList.forEach(tableName -> {
            String tableSuffix = tableName.substring(tableName.lastIndexOf("_") + 1);
            if (Integer.valueOf(tableSuffix) >= (Integer.parseInt(finalLowerSuffix)) && Integer.valueOf(tableSuffix) <= (Integer.parseInt(finalUpperSuffix))) {
                result.add(tableName);
            }
        });
        return result;
    }

配置分表策略


    <sharding:standard-strategy id="相关ShardingStrategy" sharding-column="分表字段" precise-algorithm-ref="XXXXStatsPreciseShardingAlgorithm" range-algorithm-ref="XXXXXStatsRangeShardingAlgorithm"/>


    <sharding:data-source id="shardingDataSource">
        <sharding:sharding-rule data-source-names="数据库名" default-data-source-name="数据库名">
            <sharding:table-rules>
                <sharding:table-rule logic-table="表名" actual-data-nodes="节点" table-strategy-ref="相关ShardingStrategy" />
            </sharding:table-rules>
        </sharding:sharding-rule>
        <sharding:props>
            <prop key="sql.show">true</prop>
        </sharding:props>
分表遇到的坑

通过id查找,更新,删除就会报错(不鞥你确定去哪张表中去查找数据)
接下来我介绍一下mybatis的方式处理的问题

@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
    @Signature(type = StatementHandler.class, method = "parameterize", args = {Statement.class})
})
public class CustomInterceptor implements Interceptor {


    private static final String STATEMENT_HANDLER_METHOD = "prepare";

    private static final String PARAMETERIZE_HANDLER_METHOD = "parameterize";


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        String method = invocation.getMethod().getName();
        switch (method) {
            case STATEMENT_HANDLER_METHOD:
                return prepare(invocation);
            case PARAMETERIZE_HANDLER_METHOD:
                return parameterize(invocation);
        }
        return invocation.proceed();
    }

    @SneakyThrows
    private Object prepare(Invocation invocation) {
        RoutingStatementHandler routingStatementHandler = (RoutingStatementHandler) PluginUtils
            .realTarget(invocation.getTarget());
        // 通过MetaObject优雅访问对象的属性,这里是访问statementHandler的属性;:MetaObject是Mybatis提供的一个用于方便、
        // 优雅访问对象属性的对象,通过它可以简化代码、不需要try/catch各种reflect异常,
        // 同时它支持对JavaBean、Collection、Map三种类型对象的操作。
        MetaObject metaObject = MetaObject.forObject(routingStatementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
            SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        // 获取mapper的Statement对象,它描述的是mapper对象的配置
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

        if (!checkMethodAddSharedingField(mappedStatement)) {
          return   invocation.proceed();
        }

        // 在sql尾部拼接分表所属属性
        BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
        String sqlStr = boundSql.getSql()+ " and " + "date_time" + " = ?";

        ReflectionUtils.setProperty(boundSql,"sql",sqlStr);

        metaObject.setValue("delegate.boundSql", boundSql);
        return invocation.proceed();
    }
   }
    ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值