乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 批处理概述与 Spring Batch 核心理念

    • Spring Batch 概述
    • Job-Instance-Execution 三层生命周期
    • 三层架构
    • Chunk 处理模型
    • Tasklet 处理模型
  • 第2章 Job与作业配置

    • Job 详解
    • Job 配置
    • JobLauncher 详解
    • JobParameters 详解
    • JobRepository 详解
  • 第3章 Step与执行模型

    • Step 详解
    • Step 配置
    • ExecutionContext 详解
    • ItemStream 与状态管理
    • StepScope 与 JobScope
  • 第4章 ItemReader数据读取

    • ItemReader 详解
    • FlatFileItemReader 详解
    • JdbcItemReader 详解
    • MultiResourceItemReader 详解
  • 第5章 ItemProcessor 数据处理

    • ItemProcessor 详解
  • 第6章 ItemWriter 数据写出

    • ItemWriter 详解
    • FlatFileItemWriter 详解
    • CompositeItemWriter 详解
    • JdbcBatchItemWriter 详解
  • 第7章 Chunk 处理与事务边界

    • Chunk 处理模型详解
    • 事务边界
  • 第8章 作业参数与启动

    • 命令行与 Web 启动
  • 第9章 监听器与拦截器

    • 监听器详解
  • 第10章 重启重试与跳过策略

    • 重启与重试
    • 跳过策略
  • 第11章 作业流与条件决策

    • 作业流与条件决策
  • 第12章 分区与并行处理

    • 分区详解
    • 并行 Step 与 Split
  • 第13章 与 Spring Boot 集成实践

    • Spring Boot 集成
  • 第15章 运维与监控

    • 大作业设计模式
    • 运维与监控

事务边界

本章定位:彻底理解 Spring Batch 的事务边界——Chunk 事务的 COMMIT/ROLLBACK 行为、多数据源下的 TransactionManager 选择和事务传播。

定义与作用

Spring Batch 的事务管理遵循 "一个 Chunk = 一个事务" 的铁律。每个 Chunk 的 Reader、Processor、Writer 操作在同一事务中执行,Chunk 结束时 COMMIT。

飞翔科技数据库管理员孔蓝的忠告:

"Spring Batch 的事务边界很简单:Chunk 多大,事务就包多大。但魔鬼在细节里——Reader 是否参与事务、Writer 用的事务管理器对不对、Reader 和 Writer 能否用不同事务——这些才是出 bug 的地方。"

核心原理

关键事务行为

阶段行为说明
Chunk 开始BEGIN开启新事务
read()事务中读取的行可能被事务锁定
process()事务中内存操作,不提交
write()事务中批量写入
成功 →COMMIT提交事务 + 更新 ExecutionContext
失败 →ROLLBACK回滚事务 + 进入容错处理

完整示例

场景一:Reader/Writer 不同数据源

@Configuration
public class MultiDataSourceBatchConfig {

    @Bean
    public PlatformTransactionManager readerTm(
            @Qualifier("readerDataSource") DataSource readerDs) {
        return new DataSourceTransactionManager(readerDs);
    }

    @Bean
    public PlatformTransactionManager writerTm(
            @Qualifier("writerDataSource") DataSource writerDs) {
        return new DataSourceTransactionManager(writerDs);
    }

    @Bean
    public Step multiDsStep(JobRepository jobRepository,
                              @Qualifier("writerTm") PlatformTransactionManager writerTm) {
        return new StepBuilder("multiDsStep", jobRepository)
                .<Order, Order>chunk(100, writerTm) // Writer 的事务管理器
                .reader(orderReader())              // 用自己的 DS
                .writer(orderWriter())              // 用另一个 DS
                .build();
    }
}

场景二:Reader 不参与事务

@Bean
@StepScope
public JdbcCursorItemReader<Order> nonTransactionalReader(DataSource ds) {
    JdbcCursorItemReader<Order> reader = new JdbcCursorItemReader<>();
    reader.setDataSource(ds);
    reader.setSql("SELECT * FROM orders");
    reader.setRowMapper(new BeanPropertyRowMapper<>(Order.class));
    reader.setUseSharedExtendedConnection(false); // Reader 使用独立连接
    return reader;
}

事务行为对比:

Reader 参与事务:
  Chunk 事务包含 Reader 的连接
  → Reader 读取的行被锁定
  → 直到 Chunk COMMIT 才释放锁
  → 适合:防止数据被并发修改

Reader 不参与事务:
  Chunk 事务只包含 Writer
  → Reader 连接在 read() 后立即释放
  → 不会长时间占用数据库锁
  → 适合:高并发读场景

易错场景与避坑

反例一:事务管理器与数据源不匹配

// ❌ Step 的事务管理器用的是 DataSource A
// ❌ Writer 用的是 DataSource B
// → Writer 的 INSERT 不在事务中 → 无法回滚!
@Bean
public Step brokenStep(JobRepository jobRepository,
                        @Qualifier("dsA_tm") PlatformTransactionManager tm,
                        @Qualifier("dsB_writer") ItemWriter<Order> writer) {
    return new StepBuilder("brokenStep", jobRepository)
            .<Order, Order>chunk(100, tm)  // TM 管理 DS-A
            .reader(reader)
            .writer(writer)                // Writer 写 DS-B
            .build();
}

反例二:Chunk Size=1 → 事务滥用

// ❌ 每条数据都开启+提交事务
.chunk(1, tx)
// 100 万条 → 100 万个事务 → COMMIT 开销极高

面试高频考点

Q1:Chunk 事务中 Reader 读到的数据在 Write 时会被其他事务修改吗?

取决于隔离级别和 useSharedExtendedConnection。如果 Reader 使用共享连接且隔离级别为 REPEATABLE_READ,读到的数据在事务期间不会被修改。如果 useSharedExtendedConnection=false,Reader 不参与事务,数据可能在读取后被修改。

Q2:如何让 JobRepository 使用独立的数据库?

①配置两个 DataSource:primaryDataSource(业务库)和 batchDataSource(元数据库)。②用 @BatchDataSource 或 BatchConfigurer 指定 batchDataSource 给 JobRepository。Step 的事务管理器使用 primaryDataSource。


上一章:Chunk 处理模型详解下一章:作业参数与启动

上一页
Chunk 处理模型详解