What is the transactionAttribute on a chunk step, and what can you tune with it?
answer
- DefaultTransactionAttribute == @Transactional knobs
- propagation / isolation / timeout / read-only
- per-chunk, not per-job
- timeout scales with chunk size
- read-only is a hint; isolation enforced by DB
basics
~10 sIt configures the chunk transaction's properties — propagation, isolation level, timeout, and read-only flag — via a DefaultTransactionAttribute. You set it on the StepBuilder to override defaults like isolation or a per-chunk timeout.
solid answer
~40 sEach chunk's transaction is driven by a TransactionAttribute (a DefaultTransactionAttribute) that Spring Batch passes to the PlatformTransactionManager. Through the StepBuilder's transactionAttribute(...) method you control the same knobs as @Transactional: propagation behavior, isolation level, timeout (seconds), and the read-only flag. Common uses: raise isolation to SERIALIZABLE for a step that must not see concurrent writes; lower it for throughput; set a timeout so a chunk that hangs on a lock aborts instead of blocking forever; mark a read-only reporting step read-only so the driver/ORM can optimize. Propagation is usually REQUIRED and rarely changed. The attribute applies per chunk transaction — it is not job-wide — so the timeout is the budget for one read-process-write cycle, and a larger chunk size may need a larger timeout.
code
java · 18 lines@Bean
public Step reportStep(JobRepository jobRepository,
PlatformTransactionManager txManager,
ItemReader<Row> reader,
ItemWriter<Row> writer) {
DefaultTransactionAttribute attr = new DefaultTransactionAttribute();
attr.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
attr.setTimeout(30); // seconds, budget for ONE chunk cycle
attr.setReadOnly(true); // hint for read-only extract step
return new StepBuilder("reportStep", jobRepository)
.<Row, Row>chunk(500, txManager)
.reader(reader)
.writer(writer)
.transactionAttribute(attr)
.build();
}go deeper
Aware you can set a transaction timeout/isolation on the step.
Names the four properties and that they mirror @Transactional.
Explains the attribute is per chunk and ties timeout to chunk size; knows read-only is a hint.
Reasons about isolation/lock-hold duration vs chunk size trade-offs and DB-specific isolation semantics.
## What the attribute is Every chunk transaction is described by an object implementing Spring's `TransactionAttribute` — in Batch this is a `DefaultTransactionAttribute`. It is the same abstraction that backs `@Transactional`; it bundles the metadata the `PlatformTransactionManager` needs to start the transaction. You set it on a step via `AbstractTaskletStepBuilder.transactionAttribute(TransactionAttribute)` (available on the chunk/tasklet builder chain). ## The tunable properties 1. **Propagation** — how this transaction relates to an existing one. Default is `PROPAGATION_REQUIRED` (join or start). Rarely changed in Batch since the framework owns the boundary. 2. **Isolation level** — `ISOLATION_DEFAULT` (the datasource default) up to `ISOLATION_SERIALIZABLE`. Raise it when the step must not observe concurrent modifications; lower it (e.g. `READ_COMMITTED`) for throughput. 3. **Timeout** — maximum seconds for the chunk transaction. `TIMEOUT_DEFAULT` (-1) means no explicit limit. Setting it means a chunk stuck on a row lock aborts and the step fails rather than hanging. 4. **Read-only flag** — a hint (`setReadOnly(true)`) that lets JDBC drivers / JPA providers optimize (e.g., skip dirty-check flush). Useful for extract/report steps that only read. ## Why it is per-chunk, not per-job The attribute governs **each individual chunk transaction**, not the whole step or job. So: - The `timeout` is the budget for **one** read-process-write cycle. If you bump chunk size from 100 to 10 000, a formerly fine timeout may now be too tight. - Isolation applies within a chunk; between chunks the framework commits and starts fresh, so long-held locks are naturally released at each commit — larger chunks hold locks longer. ## Gotchas - Setting a **timeout smaller than a chunk realistically needs** turns a slow-but-healthy step into intermittent failures. Tune with chunk size in mind. - Read-only is a **hint**, not enforcement; it does not prevent writes, it enables optimizations. Do not rely on it to block accidental writes. - Isolation is enforced by the **database**, not Batch; support varies by engine (e.g., how SERIALIZABLE is implemented differs). ## Java configuration Build a `DefaultTransactionAttribute`, set its properties, and hand it to the builder. See the code example. ## Key classes - `TransactionAttribute` / `DefaultTransactionAttribute` — the config object. - `TransactionDefinition` constants — `ISOLATION_*`, `PROPAGATION_*`, `TIMEOUT_DEFAULT`. - `StepBuilder` → `.chunk(...).transactionManager(...)` and `.transactionAttribute(...)`.
- You raise chunk size from 100 to 5000 and now get transaction-timeout errors. Why?The transactionAttribute timeout is per chunk. A 50x larger chunk takes proportionally longer to read/process/write within one transaction, so it can exceed a timeout that was fine for 100 items. Increase the timeout (or keep the chunk smaller).
- Does setting read-only=true prevent the writer from inserting rows?No. Read-only is an optimization hint to the driver/ORM (e.g., skip flush/dirty-check), not an enforcement. Writes may still succeed or fail depending on the resource; it is not a guard against accidental writes.
saying these in an interview costs you the question
- Thinking the timeout applies to the whole job or step rather than each chunk
- Believing read-only strictly forbids writes
- Assuming Spring Batch enforces isolation rather than the database