How to Safely Split Distributed Transactions in Java: A Practical Guide

This article explains how to handle distributed consistency when a business operation writes to MySQL and calls external systems, using a financial reimbursement example to illustrate risks, analyzes the root cause, and presents a step‑by‑step solution that splits the large transaction into small, retryable units with code snippets and Spring optimization.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
How to Safely Split Distributed Transactions in Java: A Practical Guide

Introduction

When a business operation requires writing MySQL data locally and invoking a third‑party system, distributed consistency becomes an issue; not all systems can use mature distributed‑transaction solutions.

Example code is pushed to gitee.com/dailycreate…[1]

Case Description

Take a financial reimbursement process that involves three systems: Document System (generates financial vouchers), BPM (workflow engine used for API calls to approve and fetch the next approver), and SAP (receives voucher data via API).

"Approve" Business Process

When an approver clicks “Approve”, the flow is:

Save business data and audit log.

Call BPM API to approve.

Call BPM API to get the latest pending approver.

If no pending approver, generate voucher and push to SAP.

Code illustration:

Process diagram
Process diagram

Risk Analysis

If steps 1 or 2 fail, the MySQL transaction rolls back, leaving all data unchanged.

If steps 1 and 2 succeed but step 3 fails, the MySQL transaction rolls back while BPM has already approved, leading to an inconsistent state where the document system has no record but BPM shows approval.

From the user’s perspective, an error is shown and a retry may cause “no permission” because the workflow has already moved forward.

Problem Analysis

The root cause is that a MySQL transaction can only control its own database; it cannot guarantee the remote system’s state.

Solution Idea

Break the large transaction into small ones. Each small transaction should contain at most one remote write, placed at the end of the method, and be retryable.

Implementation Steps

1. Create a task table transaction_job to store the data needed for each small transaction.

CREATE TABLE `transaction_job` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `type` varchar(255) NOT NULL COMMENT '任务类型',
  `data` varchar(255) NOT NULL COMMENT '任务数据',
  `error_message` varchar(255) DEFAULT NULL COMMENT '错误信息',
  `context` varchar(255) DEFAULT NULL COMMENT '任务上下文(主要是保存当前操作人)',
  `create_time` bigint(20) NOT NULL COMMENT '创建时间',
  `update_time` bigint(20) NOT NULL COMMENT '更新时间',
  `retry_times` int(11) NOT NULL DEFAULT '0' COMMENT '重试次数',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='事务任务表';

2. A scheduled job scans transaction_job for unfinished records and executes the corresponding small transaction using a strategy‑pattern implementation.

3. Refactor business code so that the first small transaction inserts a row into transaction_job for the second step.

Images illustrating task scanning, task execution, and the strategy‑pattern interface:

Task scanning
Task scanning
Task execution
Task execution
Strategy interface
Strategy interface

Optimization

To avoid user‑visible latency, use Spring’s TransactionSynchronizationManager.afterCommit() to insert the task only after the first transaction commits, making the second step appear instantaneous.

Note: the task may be picked up immediately by the scheduler, so locking or status checks are required to prevent duplicate execution.

Conclusion

The article presents the core idea of splitting distributed transactions; additional features will be added in future updates.

References

[1] https://link.juejin.cn?target=https%3A%2F%2Fgitee.com%2Fdailycreatebug%2Fdemo-codes

MySQLdistributed transactionBPMtransactional design
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.