SpringBatch历史数据的清理方案及实现
需求背景
SpringBatch的程序已经运行了将近一年,数据量已经达到了一定的数据量级别。
对SpringBatch历史数据的清理也被提上日程。
但是SpringBatch的代码中似乎没有找到清理历史数据的代码,在官方文档中也没有提到如何清理历史数据。
在网上查找了诸多的资料之后(不知道为什么国内关于这一点的资料非常少,但是幸好外网有不少的讨论和研究),结合自己对于SpringBatch的了解,得到了如下的清理方案。
清理方案
场景一 如果你想要清理所有的SpringBatch的数据
方案一 手动执行数据库脚本
如果你想要通过执行SQL清理所有的SpringBatch的数据,如果你使用的是Mysql数据库,你可以执行如下脚本:
DROP TABLE IF EXISTS BATCH_STEP_EXECUTION_CONTEXT;
DROP TABLE IF EXISTS BATCH_JOB_EXECUTION_CONTEXT;
DROP TABLE IF EXISTS BATCH_STEP_EXECUTION;
DROP TABLE IF EXISTS BATCH_JOB_EXECUTION_PARAMS;
DROP TABLE IF EXISTS BATCH_JOB_EXECUTION;
DROP TABLE IF EXISTS BATCH_JOB_INSTANCE;
DROP TABLE IF EXISTS BATCH_STEP_EXECUTION_SEQ;
DROP TABLE IF EXISTS BATCH_JOB_EXECUTION_SEQ;
DROP TABLE IF EXISTS BATCH_JOB_SEQ;
有或者你使用的是其他类型的数据库,下面的连接可以帮助你找到执行脚本。
https://github.com/spring-projects/spring-batch/tree/main/spring-batch-core/src/main/resources/org/springframework/batch/core
方案二 修改Spring Batch的配置
你可以修改SpringBatch的配置,如下所示:
spring.batch.initialize-schema = always
这会让Spring Batch程序启动时都会初始化数据库。
场景二 删除超过指定时间的历史数据(重点)
实际使用的时候,可能更多的场景是这一种。假如我们生产环境使用了SpringBatch,我们清理数据肯定不能够将数据完全清空。只能说我清楚一段时间之前的,例如超过了30天的数据。
需要注意的是,SpringBatch创建的制品库是有外键关联的,如下图所示:
所以如果删除表的数据的时候,需要关注删除的顺序。
方案一 直接操作删除SpringBatch的数据表的数据(重点)
Spring Batch的生成的表共有9个,其中有6个表的数据需要清理。考虑到这些表之间的外键关系,删除表的顺序必须是:
- BATCH_STEP_EXECUTION_CONTEXT
- BATCH_STEP_EXECUTION
- BATCH_JOB_EXECUTION_CONTEXT
- BATCH_JOB_EXECUTION_PARAMS
- BATCH_JOB_EXECUTION
- BATCH_JOB_INSTANCE
可供参考的数据库脚本是:
DELETE FROM BATCH_STEP_EXECUTION_CONTEXT WHERE STEP_EXECUTION_ID IN (SELECT STEP_EXECUTION_ID FROM BATCH_STEP_EXECUTION WHERE JOB_EXECUTION_ID IN (SELECT JOB_EXECUTION_ID FROM BATCH_JOB_EXECUTION where CREATE_TIME < ?))
DELETE FROM BATCH_STEP_EXECUTION WHERE JOB_EXECUTION_ID IN (SELECT JOB_EXECUTION_ID FROM BATCH_JOB_EXECUTION where CREATE_TIME < ?)
DELETE FROM BATCH_JOB_EXECUTION_CONTEXT WHERE JOB_EXECUTION_ID IN (SELECT JOB_EXECUTION_ID FROM BATCH_JOB_EXECUTION where CREATE_TIME < ?)
DELETE FROM BATCH_JOB_EXECUTION_PARAMS WHERE JOB_EXECUTION_ID IN (SELECT JOB_EXECUTION_ID FROM BATCH_JOB_EXECUTION where CREATE_TIME < ?)
DELETE FROM BATCH_JOB_EXECUTION where CREATE_TIME < ?
DELETE FROM BATCH_JOB_INSTANCE WHERE JOB_INSTANCE_ID NOT IN (SELECT JOB_INSTANCE_ID FROM BATCH_JOB_EXECUTION)
实际代码可以参考相关链接3提供的Github上的源码。
注意如果数据量很大的情况下可以考虑分页删除的功能。
相关链接
1. Spring Batch的Issues中对于历史数据清理的讨论
2. stackoverflow上关于如何清理SpringBatch历史数据的讨论
3. Github上现成的删除超时指定时间的历史数据的代码