附录 B. Meta-Data Schema

B.1 概述

Spring Batch Meta-Data 表非常接近匹配在 Java 中表示它们的 Domain objects。例如,JobInstanceJobExecutionJobParametersStepExecution map 分别为 BATCHJOB_INSTANCE,BATCHJOB_EXECUTION,BATCHJOB_EXECUTION_PARAMS 和 BATCHSTEP_EXECUTION。 ExecutionContext maps 到 BATCHJOB_EXECUTIONCONTEXT 和 BATCHSTEP_EXECUTIONCONTEXT。 JobRepository负责将每个 Java object 保存并存储到其正确的 table 中。以下附录详细描述了 meta-data 表,以及创建它们时做出的许多设计决策。在查看下面的各种 table 创建语句时,重要的是要认识到所使用的数据类型尽可能通用。 Spring Batch 提供了许多模式作为示例,由于各个数据库供应商处理数据类型的变化,它们都具有不同的数据类型。下面是所有 6 个表的 ERD model 及其相互关系:

B.1.1 Example DDL 脚本

Spring Batch Core JAR 文件包含 example 脚本,用于为许多数据库平台创建关系表(由 job repository factory bean 或等效命名空间依次为 auto-detected)。这些脚本可以按原样使用,也可以根据需要使用其他索引和约束进行修改。文件名的格式为schema-*.sql,其中“*”是目标数据库平台的短 name。脚本位于包org.springframework.batch.core中。

B.1.2 版本

本附录中讨论的许多数据库表都包含 version 列。此列很重要,因为 Spring Batch 在处理数据库更新时采用了乐观锁定策略。这意味着每个 time a record 被“触摸”(更新)version 列中的 value 加 1。当 repository 返回尝试并保存 value 时,如果 version number 已更改,它将抛出OptimisticLockingFailureException,表示并发访问时出错。此检查是必要的,因为即使不同的批处理作业可能在不同的计算机中运行,它们都使用相同的数据库表。

B.1.3 身份

BATCHJOB_INSTANCE,BATCHJOB_EXECUTION 和 BATCHSTEP_EXECUTION 各包含以_ID 结尾的列。这些字段充当各自表的主键。但是,它们不是数据库生成的密钥,而是由单独的 sequences 生成。这是必要的,因为在将一个 domain objects 插入数据库之后,需要在实际的 object 上设置它所给出的 key,以便它们可以在 Java 中唯一标识。较新的数据库驱动程序(Jdbc 3.0 及更高版本)使用数据库生成的密钥支持此 feature,但不是要求它,而是使用了 sequences。 schema 的每个变体都包含以下某种形式:

CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ;
CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ;
CREATE SEQUENCE BATCH_JOB_SEQ;

许多数据库供应商不支持 sequences。在这些情况下,使用 work-arounds,例如 MySQL 的以下内容:

CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT NOT NULL) type=InnoDB;
INSERT INTO BATCH_STEP_EXECUTION_SEQ values(0);
CREATE TABLE BATCH_JOB_EXECUTION_SEQ (ID BIGINT NOT NULL) type=InnoDB;
INSERT INTO BATCH_JOB_EXECUTION_SEQ values(0);
CREATE TABLE BATCH_JOB_SEQ (ID BIGINT NOT NULL) type=InnoDB;
INSERT INTO BATCH_JOB_SEQ values(0);

在上述情况下,使用 table 代替每个序列。然后 Spring 核心 class MySQLMaxValueIncrementer将在 order 中按此顺序递增一列以提供类似的功能。

B.2 BATCHJOB_INSTANCE

BATCHJOB_INSTANCE table 保存与JobInstance相关的所有信息,并作为整个层次结构的顶部。以下通用 DDL 语句用于创建它:

CREATE TABLE BATCH_JOB_INSTANCE  (
  JOB_INSTANCE_ID BIGINT  PRIMARY KEY ,
  VERSION BIGINT,
  JOB_NAME VARCHAR(100) NOT NULL ,
  JOB_KEY VARCHAR(2500)
);

以下是 table 中每列的说明:

  • JOB_INSTANCE_ID:将标识实例的唯一 ID,也是主 key。应通过调用JobInstance上的getId方法获取此列的 value。

  • VERSION:见上一节。

  • JOBNAME:从Job object 获取的 job 的 Name。因为需要标识实例,所以它不能为 null。

  • JOBKEY:JobParameters的序列化,它唯一地标识相同 job 的不同实例。 (具有相同 job name 的JobInstances必须具有不同的JobParameters,因此具有不同的 JOBKEY 值)。

B.3 BATCHJOB_EXECUTION_PARAMS

BATCHJOB_EXECUTION_PARAMS table 包含与JobParameters object 相关的所有信息。它包含传递给Job的 0 或更多 key/value 对,并作为 job 与 run 一起使用的参数的 record。对于有助于生成 job 标识的每个参数,IDENTIFYING flag 设置为 true。应该注意,table 已被非规范化。而不是为每种类型创建单独的 table,有一个 table,其中一列指示类型:

CREATE TABLE BATCH_JOB_EXECUTION_PARAMS  (
	JOB_EXECUTION_ID BIGINT NOT NULL ,
	TYPE_CD VARCHAR(6) NOT NULL ,
	KEY_NAME VARCHAR(100) NOT NULL ,
	STRING_VAL VARCHAR(250) ,
	DATE_VAL DATETIME DEFAULT NULL ,
	LONG_VAL BIGINT ,
	DOUBLE_VAL DOUBLE PRECISION ,
	IDENTIFYING CHAR(1) NOT NULL ,
	constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
	references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
);

以下是每列的说明:

  • JOB_EXECUTION_ID:来自 BATCHJOB_EXECUTION table 的外部 Key,表示参数条目所属的 job 执行。应该注意,每次执行可能存在多行(i.e key/value 对)。

  • TYPE_CD:string 表示存储的 value 类型,可以是 string,date,long 或 double。因为必须知道类型,所以它不能为 null。

  • KEYNAME:参数 key。

  • STRING_VAL:参数 value,如果类型是 string。

  • DATE_VAL:参数 value,如果类型为 date。

  • LONG_VAL:参数 value,如果类型是 long。

  • DOUBLE_VAL:参数 value,如果类型为 double。

  • IDENTIFYING:Flag 指示参数是否有助于相关JobInstance的标识。

值得注意的是,这个 table 没有主要的 key。这只是因为 framework 对一个没用,因此不需要它。如果用户如此选择,可以添加一个数据库生成的 key,而不会对 framework 本身造成任何问题。

B.4 BATCHJOB_EXECUTION

BATCHJOB_EXECUTION table 包含与JobExecution object 相关的所有信息。每 time是 run,总会有一个新的JobExecution,并且在这个 table 中有一个新行:

CREATE TABLE BATCH_JOB_EXECUTION  (
  JOB_EXECUTION_ID BIGINT  PRIMARY KEY ,
  VERSION BIGINT,
  JOB_INSTANCE_ID BIGINT NOT NULL,
  CREATE_TIME TIMESTAMP NOT NULL,
  START_TIME TIMESTAMP DEFAULT NULL,
  END_TIME TIMESTAMP DEFAULT NULL,
  STATUS VARCHAR(10),
  EXIT_CODE VARCHAR(20),
  EXIT_MESSAGE VARCHAR(2500),
  LAST_UPDATED TIMESTAMP,
  JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
  constraint JOB_INSTANCE_EXECUTION_FK foreign key (JOB_INSTANCE_ID)
  references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;

以下是每列的说明:

  • JOB_EXECUTION_ID:唯一标识此执行的主 key。可以通过调用JobExecution object 的getId方法获得此列的 value。

  • VERSION:见上一节。

  • JOB_INSTANCE_ID:来自 BATCHJOB_INSTANCE table 的外部 key,表示此执行所属的实例。每个实例可能有多个执行。

  • CREATETIME:表示创建执行的 time 的时间戳。

  • STARTTIME:表示执行开始的 time 的时间戳。

  • ENDTIME:表示执行完成 time 的时间戳,无论成功与否。即使 job 当前不是 running,此列中的空 value 表示存在某种类型的错误,并且 framework 在失败之前无法执行上次保存。

  • STATUS:表示执行状态的字符 string。这可能是 COMPLETED,STARTED 等。此列的 object 表示是BatchStatus枚举。

  • EXITCODE:表示执行的退出 code 的字符 string。在命令 line job 的情况下,可以将其转换为数字。

  • EXIT_MESSAGE:字符 string 表示 job 如何退出的更详细描述。在失败的情况下,这可能包括尽可能多的堆栈跟踪。

  • LAST_UPDATED:表示此执行持久的最后 time 的时间戳。

B.5 BATCHSTEP_EXECUTION

BATCHSTEP_EXECUTION table 包含与StepExecution object 相关的所有信息。这个 table 在很多方面与 BATCHJOB_EXECUTION table 非常相似,每个JobExecution创建的每个Step总会至少有一个条目:

CREATE TABLE BATCH_STEP_EXECUTION  (
  STEP_EXECUTION_ID BIGINT  PRIMARY KEY ,
  VERSION BIGINT NOT NULL,
  STEP_NAME VARCHAR(100) NOT NULL,
  JOB_EXECUTION_ID BIGINT NOT NULL,
  START_TIME TIMESTAMP NOT NULL ,
  END_TIME TIMESTAMP DEFAULT NULL,
  STATUS VARCHAR(10),
  COMMIT_COUNT BIGINT ,
  READ_COUNT BIGINT ,
  FILTER_COUNT BIGINT ,
  WRITE_COUNT BIGINT ,
  READ_SKIP_COUNT BIGINT ,
  WRITE_SKIP_COUNT BIGINT ,
  PROCESS_SKIP_COUNT BIGINT ,
  ROLLBACK_COUNT BIGINT ,
  EXIT_CODE VARCHAR(20) ,
  EXIT_MESSAGE VARCHAR(2500) ,
  LAST_UPDATED TIMESTAMP,
  constraint JOB_EXECUTION_STEP_FK foreign key (JOB_EXECUTION_ID)
  references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

以下是每列的说明:

  • STEP_EXECUTION_ID:唯一标识此执行的主 key。应通过调用StepExecution object 的getId方法获取此列的 value。

  • VERSION:见上一节。

  • STEPNAME:此执行所属的 step 的 name。

  • JOB_EXECUTION_ID:来自 BATCHJOB_EXECUTION table 的外部 key,表示此 StepExecution 所属的 JobExecution。对于给定的Step name,给定JobExecution可能只有一个StepExecution

  • STARTTIME:表示执行开始的 time 的时间戳。

  • ENDTIME:表示执行完成 time 的时间戳,无论成功与否。即使 job 当前不是 running,此列中的空 value 表示存在某种类型的错误,并且 framework 在失败之前无法执行上次保存。

  • STATUS:表示执行状态的字符 string。这可能是 COMPLETED,STARTED 等。此列的 object 表示是BatchStatus枚举。

  • COMMIT_COUNT:step 在执行期间提交 transaction 的次数。

  • READ_COUNT:执行期间读取的项目数。

  • FILTER_COUNT:从此执行中过滤掉的项目数。

  • WRITE_COUNT:在执行期间写入和提交的项目数。

  • READ_SKIP_COUNT:执行期间跳过的项目数。

  • WRITE_SKIP_COUNT:执行期间写入时跳过的项目数。

  • PROCESS_SKIP_COUNT:执行期间处理期间跳过的项目数。

  • ROLLBACK_COUNT:执行期间的回滚次数。请注意,此计数包括每次 time 回滚发生,包括重试的回滚和跳过恢复过程中的回滚。

  • EXITCODE:表示执行的退出 code 的字符 string。在命令 line job 的情况下,可以将其转换为数字。

  • EXIT_MESSAGE:字符 string 表示 job 如何退出的更详细描述。在失败的情况下,这可能包括尽可能多的堆栈跟踪。

  • LAST_UPDATED:表示此执行持久的最后 time 的时间戳。

B.6 BATCHJOB_EXECUTIONCONTEXT

BATCHJOB_EXECUTIONCONTEXT table 保存与JobExecutionContext相关的所有信息。每个JobExecution只有一个Job ExecutionContext,它包含特定 job 执行所需的所有 job-level 数据。此数据通常表示在失败后必须检索的 state,以便JobInstance可以“从它停止的位置开始”。

CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT  (
  JOB_EXECUTION_ID BIGINT PRIMARY KEY,
  SHORT_CONTEXT VARCHAR(2500) NOT NULL,
  SERIALIZED_CONTEXT CLOB,
  constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
  references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

以下是每列的说明:

  • JOB_EXECUTION_ID:表示 context 所属的JobExecution的外部 key。可能存在与给定执行相关联的多个行。

  • SHORTCONTEXT:SERIALIZEDCONTEXT 的 string version。

  • SERIALIZEDCONTEXT:整个 context,序列化。

B.7 BATCHSTEP_EXECUTIONCONTEXT

BATCHSTEP_EXECUTIONCONTEXT table 保存与StepExecutionContext相关的所有信息。每个StepExecution只有一个ExecutionContext,它包含了特定 step 执行所需的所有数据。此数据通常表示在失败后必须检索的 state,以便JobInstance可以“从它停止的位置开始”。

CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT  (
  STEP_EXECUTION_ID BIGINT PRIMARY KEY,
  SHORT_CONTEXT VARCHAR(2500) NOT NULL,
  SERIALIZED_CONTEXT CLOB,
  constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
  references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
) ;

以下是每列的说明:

  • STEP_EXECUTION_ID:表示 context 所属的StepExecution的外部 key。可能存在与给定执行相关联的多个行。

  • SHORTCONTEXT:SERIALIZEDCONTEXT 的 string version。

  • SERIALIZEDCONTEXT:整个 context,序列化。

B.8 存档

因为每个 time 时都有多个表中的条目 job 是 run,所以 common 为 meta-data 表创建归档策略。这些表本身旨在显示过去发生的事情的记录,并且通常不会影响任何 job 的 run,并且有几个与重启有关的值得注意的 exceptions:

  • framework 将使用 meta-data 表来确定特定的 JobInstance 之前是否已经 run。如果它是 run,并且 job 不可重新启动,那么将抛出 exception。

  • 如果在未成功完成的情况下删除了 JobInstance 的条目,framework 将认为 job 是新的,而不是重新启动。

  • 如果重新启动 job,framework 将使用已持久保存到 ExecutionContext 的任何数据来恢复 Job 的 state。因此,如果 run 再次运行,则删除此 table 中未成功完成的作业的任何条目将阻止它们从正确的点开始。

B.9 国际和 Multi-byte 字符

如果在业务处理中使用 multi-byte character sets(e.g. Chines 或 Cyrillic),则可能需要在 Spring Batch schema 中保留这些字符。许多用户发现只需将 schema 更改为 double VARCHAR列的长度即可。其他人更喜欢用max-varchar-length配置JobRepository 列长度的 value 的一半就足够了。一些用户还报告说他们在 schema 定义中使用NVARCHAR代替VARCHAR。最佳结果取决于数据库平台以及本地配置数据库服务器的方式。

B.10 索引元数据表的建议

Spring Batch 为几个 common 数据库平台的 Core jar 文件中的 meta-data 表提供了 DDL samples。索引声明不包含在该 DDL 中,因为用户可能希望根据其精确平台,本地约定以及作业运行方式的业务要求进行索引的变化太多。下面的 table 通过 Spring Batch 提供的 Dao implementations 提供了一些关于 WHERE 子句中将使用哪些列的指示,以及它们可以使用的频率,以便各个项目可以自己构建关于索引的思路。

表格 1_.SQL 语句中的子句(主键除外)及其大致使用频率.

默认 Table Name条款频率
BATCHJOB_INSTANCEJOBNAME =?和 JOBKEY =?每 time 启动一次 job
BATCHJOB_EXECUTIONJOB_INSTANCE_ID =?每隔 time 重启 job
BATCH_EXECUTIONCONTEXTEXECUTION_ID =?和 KEYNAME =?在提交间隔,a.k.a。块
BATCHSTEP_EXECUTIONVERSION =?在提交间隔,a.k.a。块(在 step 的开头和结尾)
BATCHSTEP_EXECUTIONSTEPNAME =?和 JOB_EXECUTION_ID =?在每个 step 执行之前
Updated at: 9 months ago
A.2. Item WritersTable of contentC.批处理和 Transactions