mysql过期数据的清理方案(Java/springboot+mybatis)

比如说现在数据库表信息增加的很快,然后我们需要对每个表设置过期删除策略;
大概思路就是:定时任务调度,给每个表制定sql,然后执行删除数据的sql

//删除一个月前的数据
delete  FROM test_info WHERE create_time < DATE_SUB(CURDATE(), INTERVAL 1 MONTH);

那么我们是不是可以把这条sql 在项目中进行执行,我这里是springboot+mybatis演示:
我们将上述sql的参数都提出来做成变量,然后调用,这里提取出来四个变量:

  • table_name :表
  • column_name:依据列(通常为时间字段 具体可以看看DATE_SUB 支:持哪些 我这里的时间类型是DATETIME)
  • expired_num:过期num
  • expired_unit:过期单位(月,天 等)
    mysql过期数据的清理方案(Java/springboot+mybatis)_第1张图片
    还有更多时间单位

现在code一下:
主要逻辑:

//思路:
//1、将表的过期处理信息制作成json,传入(这里的json可以管理起来,甚至于是数据表/redis的value),这里演示就直接以json的形式
//2、遍历 :拿到每个表的参数,并调用mybatis的mapper(绑定了xml)
//3、做好参数校验,防止注入风险,因为我们这块业务不对外暴露,所以只需要做简单的校验
//4、此时该方法就可以做成接口,甚至于定时任务等形式来处理过期数据
//5、做成这样放在项目内好管理,当然也可以做python脚本等形式,主要就是sql的调用,并做成合理的链
    public void clearExpiredData() {
        try {
            String inputData = "[{\"table_name\":\"test_info\",\"column_name\":\"create_time\",\"expired_num\":\"4\",\"expired_unit\":\"MONTH\"}," +
                    "{\"table_name\":\"test_info\",\"column_name\":\"create_time\",\"expired_num\":\"30\",\"expired_unit\":\"DAY\"}]";
            if (JSON.isValid(inputData)) {
                String tableNameFiled = "table_name";
                String columnNameFiled = "column_name";
                String expiredNumFiled = "expired_num";
                String expiredUnitFiled = "expired_unit";
                JSONArray jsonArray = JSON.parseArray(inputData);
                Iterator iterator = jsonArray.stream().iterator();
                while (iterator.hasNext()) {
                    JSONObject next = null;
                    try {
                        next = (JSONObject) iterator.next();
                        //校验包含特定的key,和过期单位必须是 DAY或者MONTH (mysql支持更多,但是这是业务)
                        if (next.containsKey(tableNameFiled) && next.containsKey(columnNameFiled) && next.containsKey(expiredNumFiled) && next.containsKey(expiredUnitFiled)
                                && (Objects.equals(next.get(expiredUnitFiled), "DAY") || (Objects.equals(next.get(expiredUnitFiled), "MONTH")))) {
                            String tableName = (String) next.get(tableNameFiled);
                            String columnName = (String) next.get(columnNameFiled);
                            String expiredNum = (String) next.get(expiredNumFiled);
                            String expiredUnit = (String) next.get(expiredUnitFiled);
                            if (!tableName.contains(" ")&&!columnName.contains(" ")&&!expiredNum.contains(" ")&&!expiredUnit.contains(" ")){//防止sql注入
                                int delExpiredDataNum = mysqlExpiredDataMapper.delExpiredData(tableName, columnName, Integer.parseInt(expiredNum), expiredUnit);
                                log.info("del expired mysql data table:{},column:{},expired:{}:{},size:{}", tableName, columnName, expiredNum, expiredUnit, delExpiredDataNum);
                            }else {
                                log.warn("current JSONObject param loss:{}, may sql inject", next.toJSONString());
                            }
                        } else {
                            log.warn("current JSONObject param loss:{}", next.toJSONString());
                        }
                    } catch (Exception e) {
                        log.error("current JSONObject param error:{}", next.toJSONString(), e);
                    }
                }
            } else {
                log.warn("valid error :{}", inputData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

mapper.java

@Repository
public interface MysqlExpiredDataMapper {
    int delExpiredData(@Param("table_name") String table, @Param("column_name") String column, @Param("expired_num") int expiredNum, @Param("expired_unit") String expiredUnit);
}

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.analysis.mapper.MysqlExpiredDataMapper">

    <delete id="delExpiredData">
        delete
        FROM ${table_name}
        WHERE ${column_name} &lt; DATE_SUB(CURDATE(), INTERVAL #{expired_num} ${expired_unit});
    </delete>
</mapper>

注意点:
1、${}和#{},的区别,是上面穿参数的关键;
2、 & l t ; 是小于号
3、存在sql注入的危险,所以要在调用的时候做好参数校验,如果业务没有暴露的情况,那么这是一个不错的方案;

如果方案有不成熟的地方,欢迎大佬指出,小子优化

你可能感兴趣的:(Working,Knowledge,java,mysql,spring,boot,mybatis,1024程序员节)