元資料模式

概述

Spring Batch 元資料表與在 Java 中表示它們的領域物件密切對應。例如,JobInstanceJobExecutionJobParametersStepExecution 分別對映到 BATCH_JOB_INSTANCEBATCH_JOB_EXECUTIONBATCH_JOB_EXECUTION_PARAMSBATCH_STEP_EXECUTIONExecutionContext 對映到 BATCH_JOB_EXECUTION_CONTEXTBATCH_STEP_EXECUTION_CONTEXTJobRepository 負責將每個 Java 物件儲存並存儲到其對應的表中。本附錄詳細描述了元資料表,以及建立它們時所做的許多設計決策。檢視本附錄後面描述的各種表建立語句時,請注意使用的資料型別儘可能通用。Spring Batch 提供了許多模式作為示例。由於各個資料庫供應商處理資料型別的方式不同,所有這些模式的資料型別各不相同。下圖顯示了所有六個表及其相互關係的 ERD 模型

Spring Batch Meta-Data ERD
圖 1. Spring Batch 元資料 ERD

示例 DDL 指令碼

Spring Batch Core JAR 檔案包含用於建立多種資料庫平臺關係表的示例指令碼(這些平臺又會被 job repository factory bean 或等效的名稱空間自動檢測到)。這些指令碼可以按原樣使用,也可以根據需要新增額外的索引和約束進行修改。檔名格式為 schema-*.sql,其中 * 是目標資料庫平臺的短名稱。這些指令碼位於 org.springframework.batch.core 包中。

遷移 DDL 指令碼

Spring Batch 提供了在升級版本時需要執行的遷移 DDL 指令碼。這些指令碼可以在 Core Jar 檔案的 org/springframework/batch/core/migration 路徑下找到。遷移指令碼按引入的版本號組織到相應的資料夾中

  • 2.2:包含從 2.2 之前版本遷移到 2.2 版本所需的指令碼

  • 4.1:包含從 4.1 之前版本遷移到 4.1 版本所需的指令碼

版本

本附錄中討論的許多資料庫表都包含一個版本列。這個列很重要,因為 Spring Batch 在處理資料庫更新時採用了樂觀鎖策略。這意味著每次“觸及”(更新)一條記錄時,版本列中的值都會加一。當 Repository 回去儲存值時,如果版本號已經改變,它會丟擲 OptimisticLockingFailureException,表示存在併發訪問錯誤。此檢查是必要的,因為即使不同的批處理作業可能在不同的機器上執行,它們都使用相同的資料庫表。

標識

BATCH_JOB_INSTANCEBATCH_JOB_EXECUTIONBATCH_STEP_EXECUTION 都包含以 _ID 結尾的列。這些欄位作為各自表的主鍵。但是,它們不是資料庫生成的鍵。相反,它們是由單獨的序列生成的。這是必要的,因為將其中一個領域物件插入資料庫後,它獲得的鍵需要設定在實際物件上,以便在 Java 中能夠唯一標識它們。較新的資料庫驅動程式(JDBC 3.0 及以上)支援資料庫生成鍵的此特性。然而,為了不強制要求該特性,使用了序列。每種模式變體都包含以下語句的某種形式

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

許多資料庫供應商不支援序列。在這種情況下,會使用變通方法,例如以下用於 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);

在上述情況下,使用一個表來代替每個序列。然後,Spring 核心類 MySQLMaxValueIncrementer 遞增此序列中的一列以提供類似的功能。

BATCH_JOB_INSTANCE

BATCH_JOB_INSTANCE 表儲存了與 JobInstance 相關的所有資訊,並作為整個層次結構的頂部。以下是用於建立它的通用 DDL 語句

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

以下列表描述了表中的每一列

  • JOB_INSTANCE_ID:唯一標識例項的 ID。它也是主鍵。此列的值應該可以透過呼叫 JobInstancegetId 方法獲得。

  • VERSION:參見版本

  • JOB_NAME:從 Job 物件獲取的作業名稱。由於它是標識例項所必需的,因此不能為空。

  • JOB_KEYJobParameters 的序列化,用於唯一標識同一作業的不同例項。(具有相同作業名稱的 JobInstances 必須具有不同的 JobParameters,因此具有不同的 JOB_KEY 值)。

BATCH_JOB_EXECUTION_PARAMS

BATCH_JOB_EXECUTION_PARAMS 表儲存了與 JobParameters 物件相關的所有資訊。它包含傳遞給 Job 的 0 個或多個鍵值對,並作為作業執行引數的記錄。對於每個有助於生成作業標識的引數,將 IDENTIFYING 標誌設定為 true。請注意,該表已進行反正規化化。沒有為每種型別建立單獨的表,而是有一個表,其中包含一個指示型別的列,如下所示

CREATE TABLE BATCH_JOB_EXECUTION_PARAMS  (
	JOB_EXECUTION_ID BIGINT NOT NULL ,
	PARAMETER_NAME VARCHAR(100) NOT NULL ,
	PARAMETER_TYPE VARCHAR(100) NOT NULL ,
	PARAMETER_VALUE VARCHAR(2500) ,
	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:來自 BATCH_JOB_EXECUTION 表的外部索引鍵,指示引數條目所屬的作業執行。請注意,每個執行可能存在多行(即鍵值對)。

  • PARAMETER_NAME:引數名稱。

  • PARAMETER_TYPE:引數型別的完全限定名稱。

  • PARAMETER_VALUE:引數值

  • IDENTIFYING:指示引數是否對相關 JobInstance 的標識產生貢獻的標誌。

請注意,此表沒有主鍵。這是因為框架不需要它,因此不強制要求。如果需要,您可以使用資料庫生成的鍵新增主鍵,而不會對框架本身造成任何問題。

BATCH_JOB_EXECUTION

BATCH_JOB_EXECUTION 表儲存了與 JobExecution 物件相關的所有資訊。每次執行 Job 時,都會有一個新的 JobExecution 呼叫以及此表中的新行。以下列出了 BATCH_JOB_EXECUTION 表的定義

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,
  constraint JOB_INSTANCE_EXECUTION_FK foreign key (JOB_INSTANCE_ID)
  references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;

以下列表描述了每一列

  • JOB_EXECUTION_ID:唯一標識此執行的主鍵。此列的值可以透過呼叫 JobExecution 物件的 getId 方法獲得。

  • VERSION:參見版本

  • JOB_INSTANCE_ID:來自 BATCH_JOB_INSTANCE 表的外部索引鍵。它指示此執行所屬的例項。每個例項可能有一個以上的執行。

  • CREATE_TIME:表示執行建立時間的 timestamp。

  • START_TIME:表示執行開始時間的 timestamp。

  • END_TIME:表示執行完成時間的 timestamp,無論成功或失敗。作業當前未執行時此列為空值,表示發生了某種錯誤,並且框架在失敗前未能執行最後一次儲存。

  • STATUS:表示執行狀態的字串。可以是 COMPLETEDSTARTED 等。此列的物件表示是 BatchStatus 列舉。

  • EXIT_CODE:表示執行退出碼的字串。對於命令列作業,這可以轉換為一個數字。

  • EXIT_MESSAGE:表示作業退出方式更詳細描述的字串。如果失敗,這可能包括儘可能多的堆疊跟蹤資訊。

  • LAST_UPDATED:表示此執行最後一次持久化時間的 timestamp。

BATCH_STEP_EXECUTION

BATCH_STEP_EXECUTION 表儲存了與 StepExecution 物件相關的所有資訊。此表在許多方面與 BATCH_JOB_EXECUTION 表相似,並且每個建立的 JobExecution 針對每個 Step 至少有一個條目。以下列出了 BATCH_STEP_EXECUTION 表的定義

CREATE TABLE BATCH_STEP_EXECUTION  (
  STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
  VERSION BIGINT NOT NULL,
  STEP_NAME VARCHAR(100) NOT NULL,
  JOB_EXECUTION_ID BIGINT NOT NULL,
  CREATE_TIME TIMESTAMP NOT NULL,
  START_TIME TIMESTAMP DEFAULT 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:唯一標識此執行的主鍵。此列的值應該可以透過呼叫 StepExecution 物件的 getId 方法獲得。

  • VERSION:參見版本

  • STEP_NAME:此執行所屬步驟的名稱。

  • JOB_EXECUTION_ID:來自 BATCH_JOB_EXECUTION 表的外部索引鍵。它指示此 StepExecution 所屬的 JobExecution。對於給定的 JobExecution 和給定的 Step 名稱,可能只有一個 StepExecution

  • START_TIME:表示執行開始時間的 timestamp。

  • END_TIME:表示執行完成時間的 timestamp,無論成功或失敗。此列為空值(即使作業當前未執行)表示發生了某種錯誤,並且框架在失敗前未能執行最後一次儲存。

  • STATUS:表示執行狀態的字串。可以是 COMPLETEDSTARTED 等。此列的物件表示是 BatchStatus 列舉。

  • COMMIT_COUNT:在此執行期間步驟已提交事務的次數。

  • READ_COUNT:在此執行期間讀取的專案數。

  • FILTER_COUNT:在此執行期間被過濾掉的專案數。

  • WRITE_COUNT:在此執行期間寫入並提交的專案數。

  • READ_SKIP_COUNT:在此執行期間讀取時跳過的專案數。

  • WRITE_SKIP_COUNT:在此執行期間寫入時跳過的專案數。

  • PROCESS_SKIP_COUNT:在此執行期間處理時跳過的專案數。

  • ROLLBACK_COUNT:在此執行期間回滾的次數。請注意,此計數包括每次發生回滾的次數,包括重試的回滾和跳過恢復過程中的回滾。

  • EXIT_CODE:表示執行退出碼的字串。對於命令列作業,這可以轉換為一個數字。

  • EXIT_MESSAGE:表示作業退出方式更詳細描述的字串。如果失敗,這可能包括儘可能多的堆疊跟蹤資訊。

  • LAST_UPDATED:表示此執行最後一次持久化時間的 timestamp。

BATCH_JOB_EXECUTION_CONTEXT

BATCH_JOB_EXECUTION_CONTEXT 表儲存了與 JobExecutionContext 相關的所有資訊。每個 JobExecution 恰好有一個 Job ExecutionContext,它包含特定作業執行所需的所有作業級別資料。此資料通常表示失敗後必須檢索的狀態,以便 JobInstance 可以“從中斷處繼續”。以下列出了 BATCH_JOB_EXECUTION_CONTEXT 表的定義

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:表示上下文所屬 JobExecution 的外部索引鍵。給定執行可能關聯多行。

  • SHORT_CONTEXTSERIALIZED_CONTEXT 的字串版本。

  • SERIALIZED_CONTEXT:整個上下文,序列化後的。

BATCH_STEP_EXECUTION_CONTEXT

BATCH_STEP_EXECUTION_CONTEXT 表儲存了與 StepExecutionContext 相關的所有資訊。每個 StepExecution 恰好有一個 ExecutionContext,它包含特定步驟執行所需的所有持久化資料。此資料通常表示失敗後必須檢索的狀態,以便 JobInstance 可以“從中斷處繼續”。以下列出了 BATCH_STEP_EXECUTION_CONTEXT 表的定義

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:表示上下文所屬 StepExecution 的外部索引鍵。給定執行可能關聯多行。

  • SHORT_CONTEXTSERIALIZED_CONTEXT 的字串版本。

  • SERIALIZED_CONTEXT:整個上下文,序列化後的。

歸檔

由於每次執行批處理作業時都會在多個表中生成條目,因此通常會為元資料表建立歸檔策略。這些表本身旨在記錄過去發生的事情,並且通常不會影響任何作業的執行,但有一些與重啟相關的顯著例外

  • 框架使用元資料表來確定特定的 JobInstance 是否之前執行過。如果執行過並且作業不可重啟,則會丟擲異常。

  • 如果刪除了尚未成功完成的 JobInstance 的條目,框架會認為該作業是新作業,而不是重啟。

  • 如果作業被重啟,框架會使用持久化到 ExecutionContext 的任何資料來恢復 Job 的狀態。因此,刪除此表中尚未成功完成的作業的任何條目,將導致它們再次執行時無法從正確的位置開始。

國際化和多位元組字元

如果您在業務處理中使用多位元組字元集(如中文或西里爾文),這些字元可能需要持久化到 Spring Batch 模式中。許多使用者發現,只需更改模式將 VARCHAR 列的長度加倍就足夠了。其他人則傾向於將 JobRepository 配置為 max-varchar-lengthVARCHAR 列長度值的一半。還有一些使用者報告說,他們在模式定義中用 NVARCHAR 替換了 VARCHAR。最佳結果取決於資料庫平臺以及資料庫伺服器在本地的配置方式。

元資料表索引建議

Spring Batch 在核心 jar 檔案中為幾種常見的資料庫平臺提供了元資料表的 DDL 示例。該 DDL 中不包含索引宣告,因為使用者可能希望如何索引有太多差異,取決於其具體的平臺、本地約定以及作業操作的業務需求。下表提供了一些指示,說明 Spring Batch 提供的 DAO 實現將在 WHERE 子句中使用哪些列以及它們可能的使用頻率,以便各個專案可以自行決定索引方式

表 1. SQL 語句中的 Where 子句(不含主鍵)及其大致使用頻率。

預設表名

Where 子句

頻率

BATCH_JOB_INSTANCE

JOB_NAME = ? and JOB_KEY = ?

每次啟動作業時

BATCH_JOB_EXECUTION

JOB_INSTANCE_ID = ?

每次重啟作業時

BATCH_STEP_EXECUTION

VERSION = ?

在提交間隔,即分塊時(以及步驟開始和結束時)

BATCH_STEP_EXECUTION

STEP_NAME = ? and JOB_EXECUTION_ID = ?

每次步驟執行前