# 前言:事务管理的艺术与哲学

在我多年的开发经历中,事务管理一直是一个既熟悉又陌生的话题。熟悉的是,几乎每个项目都需要用到事务;陌生的是,真正理解事务本质的人却寥寥无几。我见过太多因为事务使用不当而导致的系统故障,也见证过优秀的事务设计如何让系统更加健壮。

记得有一次,我接手了一个电商系统,发现订单处理逻辑中存在严重的事务问题:用户下单时,库存扣减和订单创建不在同一个事务中,导致超卖现象频发。这个问题不仅造成了经济损失,更严重影响了用户体验。通过重新设计事务边界,我们彻底解决了这个问题。

Spring 的事务管理机制是 Java 企业级开发中最优雅的设计之一。它将复杂的事务处理逻辑封装起来,让开发者能够专注于业务逻辑。但正是这种封装,让很多开发者对事务的内部原理缺乏深入理解。

今天,我想和大家分享我对 Spring 事务管理的深度思考和实战经验,希望能帮助你真正掌握这门重要的技术。

# 事务基础理论:ACID 与隔离级别

# 什么是事务?

事务是数据库操作的基本单位,它是一个不可分割的工作序列。想象一下银行转账的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 银行转账伪代码
public void transfer(Long fromId, Long toId, BigDecimal amount) {
// 1. 检查转出账户余额
Account fromAccount = accountDao.findById(fromId);
if (fromAccount.getBalance().compareTo(amount) < 0) {
throw new InsufficientBalanceException("余额不足");
}

// 2. 扣减转出账户余额
fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
accountDao.update(fromAccount);

// 3. 增加转入账户余额
Account toAccount = accountDao.findById(toId);
toAccount.setBalance(toAccount.getBalance().add(amount));
accountDao.update(toAccount);
}

如果没有事务保护,当第 2 步执行成功但第 3 步失败时,钱就会凭空消失!事务确保这组操作要么全部成功,要么全部失败。

# ACID 四大特性

# 1. 原子性(Atomicity)

事务中的所有操作要么全部完成,要么全部不完成。

1
2
3
4
5
6
@Transactional
public void transfer(Long fromId, Long toId, BigDecimal amount) {
// 这些操作要么全部成功,要么全部失败
deductBalance(fromId, amount);
addBalance(toId, amount);
}

# 2. 一致性(Consistency)

事务执行前后,数据库都处于一致的状态。

1
2
3
4
5
6
7
8
9
10
11
@Transactional
public void placeOrder(Order order) {
// 业务一致性:订单金额必须等于商品单价 × 数量
BigDecimal totalAmount = order.getUnitPrice().multiply(BigDecimal.valueOf(order.getQuantity()));
if (!order.getTotalAmount().equals(totalAmount)) {
throw new BusinessException("订单金额不一致");
}

orderDao.save(order);
inventoryDao.reduceStock(order.getProductId(), order.getQuantity());
}

# 3. 隔离性(Isolation)

并发事务之间相互隔离,不会相互干扰。

# 4. 持久性(Durability)

事务一旦提交,对数据库的修改就是永久性的。

# 事务隔离级别

不同的隔离级别在并发性能和数据一致性之间做权衡:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 演示不同隔离级别的效果
*/
@Service
public class TransactionIsolationDemo {

/**
* READ_UNCOMMITTED:读未提交
* 可能出现脏读、不可重复读、幻读
*/
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void readUncommitted() {
// 可以读取到其他事务未提交的数据
Product product = productDao.findById(1L);
System.out.println("读取到未提交的数据:" + product.getPrice());
}

/**
* READ_COMMITTED:读已提交
* 避免脏读,但可能出现不可重复读、幻读
*/
@Transactional(isolation = Isolation.READ_COMMITTED)
public void readCommitted() {
// 只能读取到其他事务已提交的数据
Product product = productDao.findById(1L);
System.out.println("读取到已提交的数据:" + product.getPrice());
}

/**
* REPEATABLE_READ:可重复读
* 避免脏读、不可重复读,但可能出现幻读
*/
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void repeatableRead() {
// 在同一事务中多次读取同一数据,结果一致
Product product1 = productDao.findById(1L);
// 模拟其他事务修改数据
try { Thread.sleep(3000); } catch (InterruptedException e) {}
Product product2 = productDao.findById(1L);
System.out.println("两次读取结果相同:" + product1.getPrice().equals(product2.getPrice()));
}

/**
* SERIALIZABLE:串行化
* 最高隔离级别,避免所有并发问题,但性能最差
*/
@Transactional(isolation = Isolation.SERIALIZABLE)
public void serializable() {
// 完全串行执行,避免所有并发问题
List<Product> products = productDao.findAll();
System.out.println("串行化读取:" + products.size());
}
}

# Spring 事务管理核心机制

# PlatformTransactionManager

Spring 事务管理的核心是 PlatformTransactionManager 接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 事务管理器的核心接口
*/
public interface PlatformTransactionManager {

/**
* 获取事务
* @param definition 事务定义信息
* @return 事务状态对象
*/
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

/**
* 提交事务
* @param status 事务状态
*/
void commit(TransactionStatus status) throws TransactionException;

/**
* 回滚事务
* @param status 事务状态
*/
void rollback(TransactionStatus status) throws TransactionException;
}

Spring 提供了多种事务管理器实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* JDBC事务管理器
*/
@Configuration
public class TransactionConfig {

/**
* JDBC事务管理器配置
*/
@Bean
public PlatformTransactionManager jdbcTransactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

/**
* JPA事务管理器配置
*/
@Bean
public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}

/**
* MyBatis事务管理器配置
*/
@Bean
public PlatformTransactionManager mybatisTransactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

/**
* JTA分布式事务管理器配置
*/
@Bean
public PlatformTransactionManager jtaTransactionManager() {
return new JtaTransactionManager();
}
}

# 事务定义 TransactionDefinition

TransactionDefinition 定义了事务的各种属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 事务定义的详细配置
*/
public class TransactionDefinitionDemo {

/**
* 编程式事务管理示例
*/
public void programmaticTransaction() {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();

// 设置传播行为
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

// 设置隔离级别
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);

// 设置超时时间(秒)
definition.setTimeout(30);

// 设置只读
definition.setReadOnly(true);

// 设置事务名称
definition.setName("programmaticTransaction");
}
}

# 事务传播行为

事务传播行为定义了事务方法之间的调用关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* 事务传播行为演示
*/
@Service
public class TransactionPropagationDemo {

/**
* REQUIRED:如果存在事务,则加入当前事务;否则创建新事务(默认)
*/
@Transactional(propagation = Propagation.REQUIRED)
public void requiredMethod() {
// 业务逻辑
innerMethod(); // 会加入当前事务
}

@Transactional(propagation = Propagation.REQUIRED)
public void innerMethod() {
// 与requiredMethod在同一个事务中
}

/**
* REQUIRES_NEW:总是创建新事务,如果存在当前事务,则挂起当前事务
*/
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void requiresNewMethod() {
// 总是在新事务中执行
logOperation(); // 会在独立的事务中执行
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOperation() {
// 独立事务,不受外部事务影响
}

/**
* SUPPORTS:如果存在事务,则加入当前事务;否则以非事务方式执行
*/
@Transactional(propagation = Propagation.SUPPORTS)
public void supportsMethod() {
// 根据调用者决定是否在事务中执行
}

/**
* NOT_SUPPORTED:总是以非事务方式执行,如果存在当前事务,则挂起当前事务
*/
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void notSupportedMethod() {
// 总是在非事务环境中执行
}

/**
* MANDATORY:必须存在事务,否则抛出异常
*/
@Transactional(propagation = Propagation.MANDATORY)
public void mandatoryMethod() {
// 必须在事务中调用,否则抛出IllegalTransactionStateException
}

/**
* NEVER:从不使用事务,如果存在当前事务,则抛出异常
*/
@Transactional(propagation = Propagation.NEVER)
public void neverMethod() {
// 绝不能在事务中调用
}

/**
* NESTED:如果存在事务,则在嵌套事务中执行;否则创建新事务
*/
@Transactional(propagation = Propagation.NESTED)
public void nestedMethod() {
// 嵌套事务,可以独立回滚
try {
// 嵌套事务操作
riskyOperation();
} catch (Exception e) {
// 只回滚嵌套事务,不影响外部事务
log.error("嵌套事务失败,但不影响外部事务", e);
}
}

public void riskyOperation() {
// 可能失败的操作
}
}

# 声明式事务实战

# 基础声明式事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* 基础的声明式事务使用
*/
@Service
@Slf4j
public class BasicTransactionService {

@Autowired
private OrderRepository orderRepository;

@Autowired
private InventoryRepository inventoryRepository;

/**
* 简单的事务方法
*/
@Transactional
public Order createOrder(Order order) {
log.info("开始创建订单:{}", order.getId());

// 保存订单
Order savedOrder = orderRepository.save(order);

// 扣减库存
inventoryRepository.reduceStock(order.getProductId(), order.getQuantity());

log.info("订单创建完成:{}", savedOrder.getId());
return savedOrder;
}

/**
* 只读事务
*/
@Transactional(readOnly = true)
public Order getOrder(Long orderId) {
return orderRepository.findById(orderId)
.orElseThrow(() -> new BusinessException("订单不存在"));
}

/**
* 带超时时间的事务
*/
@Transactional(timeout = 30) // 30秒超时
public void batchProcess(List<Order> orders) {
for (Order order : orders) {
processOrder(order);
}
}

/**
* 指定回滚异常
*/
@Transactional(rollbackFor = {BusinessException.class, SystemException.class})
public void riskyOperation() throws BusinessException {
// 业务逻辑
if (someCondition()) {
throw new BusinessException("业务异常,会触发回滚");
}
}

/**
* 不回滚的异常
*/
@Transactional(noRollbackFor = {BusinessWarningException.class})
public void warningOperation() throws BusinessWarningException {
// 即使抛出BusinessWarningException,也不会回滚
if (warningCondition()) {
throw new BusinessWarningException("业务警告,不触发回滚");
}
}

private boolean someCondition() {
return true;
}

private boolean warningCondition() {
return true;
}

private void processOrder(Order order) {
// 处理订单逻辑
}
}

# 复杂事务场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* 复杂事务场景处理
*/
@Service
@Slf4j
public class ComplexTransactionService {

@Autowired
private UserRepository userRepository;

@Autowired
private AccountRepository accountRepository;

@Autowired
private TransactionTemplate transactionTemplate; // 编程式事务

/**
* 场景1:事务中调用非事务方法
*/
@Transactional
public void updateUserWithNonTransactionalMethod(User user) {
userRepository.save(user);
updateAccountInfo(user); // 这个方法不在事务中
}

/**
* 非事务方法
*/
public void updateAccountInfo(User user) {
// 这里不会在事务中执行
Account account = accountRepository.findByUserId(user.getId());
account.setUpdateTime(new Date());
accountRepository.save(account);
}

/**
* 场景2:解决自调用问题 - 方案1:注入自身
*/
@Autowired
private ComplexTransactionService self;

@Transactional
public void updateWithSelfCall(User user) {
userRepository.save(user);
self.updateAccountInTransaction(user); // 通过代理调用
}

@Transactional
public void updateAccountInTransaction(User user) {
Account account = accountRepository.findByUserId(user.getId());
account.setUpdateTime(new Date());
accountRepository.save(account);
}

/**
* 场景3:解决自调用问题 - 方案2:使用AopContext
*/
@Transactional
public void updateWithAopContext(User user) {
userRepository.save(user);
((ComplexTransactionService) AopContext.currentProxy())
.updateAccountInTransaction(user);
}

/**
* 场景4:编程式事务
*/
public void programmaticTransaction(User user) {
transactionTemplate.execute(status -> {
try {
userRepository.save(user);
updateAccountInfo(user);
return "success";
} catch (Exception e) {
status.setRollbackOnly();
return "failed";
}
});
}

/**
* 场景5:嵌套事务
*/
@Transactional
public void nestedTransactionExample(User user) {
userRepository.save(user);

try {
nestedOperation(user);
} catch (Exception e) {
log.error("嵌套事务失败,但不影响主事务", e);
}

// 主事务继续执行
user.setStatus("COMPLETED");
userRepository.save(user);
}

@Transactional(propagation = Propagation.NESTED)
public void nestedOperation(User user) {
// 嵌套事务操作
Account account = new Account();
account.setUserId(user.getId());
account.setBalance(BigDecimal.ZERO);
accountRepository.save(account);

// 模拟异常
if (account.getBalance().equals(BigDecimal.ZERO)) {
throw new BusinessException("账户余额不能为零");
}
}

/**
* 场景6:不同传播行为的组合
*/
@Transactional
public void propagationBehaviorExample(User user) {
userRepository.save(user);

// REQUIRES_NEW:在新事务中执行
requiresNewLog(user.getId());

// NESTED:嵌套事务
nestedValidation(user);

// SUPPORTS:支持事务
supportsOperation(user);
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void requiresNewLog(Long userId) {
// 独立事务,用于记录日志
logRepository.insertLog(userId, "用户操作", new Date());
}

@Transactional(propagation = Propagation.NESTED)
public void nestedValidation(User user) {
// 嵌套事务,用于验证
if (user.getEmail() == null) {
throw new BusinessException("邮箱不能为空");
}
}

@Transactional(propagation = Propagation.SUPPORTS)
public void supportsOperation(User user) {
// 如果调用者有事务,则加入;否则非事务执行
cacheService.refreshUserCache(user.getId());
}

@Autowired
private LogRepository logRepository;

@Autowired
private CacheService cacheService;
}

# 事务失效的常见原因与解决方案

# 1. 访问权限问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* ❌ 错误示例:private方法无法被代理
*/
@Service
public class TransactionFailureExample1 {

@Transactional
private void privateMethod() {
// 事务不会生效
}

/**
* ✅ 正确示例:使用public方法
*/
@Transactional
public void publicMethod() {
// 事务生效
}

/**
* ✅ 解决方案:public方法调用private方法
*/
@Transactional
public void wrapperMethod() {
privateMethod(); // 在事务中调用
}
}

# 2. 自调用问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* ❌ 错误示例:自调用导致AOP失效
*/
@Service
public class TransactionFailureExample2 {

@Transactional
public void methodA() {
methodB(); // 自调用,不会触发事务
}

@Transactional
public void methodB() {
// 事务不会生效
}
}

/**
* ✅ 解决方案1:注入自身代理
*/
@Service
public class TransactionSolution2_1 {

@Autowired
private TransactionSolution2_1 self;

@Transactional
public void methodA() {
self.methodB(); // 通过代理调用
}

@Transactional
public void methodB() {
// 事务生效
}
}

/**
* ✅ 解决方案2:使用AopContext
*/
@Service
public class TransactionSolution2_2 {

@Transactional
public void methodA() {
((TransactionSolution2_2) AopContext.currentProxy()).methodB();
}

@Transactional
public void methodB() {
// 事务生效
}
}

# 3. 异常处理问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* ❌ 错误示例:捕获异常不抛出
*/
@Service
public class TransactionFailureExample3 {

@Transactional
public void methodWithTryCatch() {
try {
riskyOperation();
} catch (Exception e) {
log.error("操作失败", e);
// 异常被捕获,事务不会回滚
}
}
}

/**
* ✅ 解决方案1:重新抛出异常
*/
@Service
public class TransactionSolution3_1 {

@Transactional
public void methodWithTryCatch() {
try {
riskyOperation();
} catch (Exception e) {
log.error("操作失败", e);
throw e; // 重新抛出异常
}
}
}

/**
* ✅ 解决方案2:手动设置回滚
*/
@Service
public class TransactionSolution3_2 {

@Transactional
public void methodWithManualRollback() {
try {
riskyOperation();
} catch (Exception e) {
log.error("操作失败", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}

# 4. 数据库引擎问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* ❌ 错误示例:使用不支持事务的存储引擎
*/
@Service
public class TransactionFailureExample4 {

@Transactional
public void operationOnMyISAM() {
// MyISAM不支持事务,@Transactional无效
myisamRepository.insert(data);
}
}

/**
* ✅ 解决方案:使用支持事务的存储引擎
*/
@Service
public class TransactionSolution4 {

@Transactional
public void operationOnInnoDB() {
// InnoDB支持事务
innodbRepository.insert(data);
}
}

# 分布式事务实战

# JTA 分布式事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* JTA分布式事务配置
*/
@Configuration
@EnableTransactionManagement
public class JtaTransactionConfig {

/**
* JTA事务管理器
*/
@Bean
public PlatformTransactionManager transactionManager() {
JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setTransactionManagerName("java:/TransactionManager");
return transactionManager;
}

/**
* 多数据源配置
*/
@Bean
@Primary
public DataSource primaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/db1")
.username("user")
.password("password")
.build();
}

@Bean
public DataSource secondaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/db2")
.username("user")
.password("password")
.build();
}
}

/**
* 分布式事务服务
*/
@Service
public class DistributedTransactionService {

@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;

@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;

/**
* 跨数据库事务
*/
@Transactional
public void crossDatabaseOperation() {
// 操作数据库1
JdbcTemplate primaryTemplate = new JdbcTemplate(primaryDataSource);
primaryTemplate.update("INSERT INTO table1 (name) VALUES (?)", "test1");

// 操作数据库2
JdbcTemplate secondaryTemplate = new JdbcTemplate(secondaryDataSource);
secondaryTemplate.update("INSERT INTO table2 (name) VALUES (?)", "test2");

// 如果任一操作失败,两个数据库都会回滚
}
}

# Saga 模式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* Saga模式实现分布式事务
*/
@Service
@Slf4j
public class SagaTransactionService {

@Autowired
private OrderService orderService;

@Autowired
private InventoryService inventoryService;

@Autowired
private PaymentService paymentService;

/**
* Saga事务编排
*/
public void executeSaga(Order order) {
List<SagaStep> steps = Arrays.asList(
new CreateOrderStep(orderService, order),
new ReduceInventoryStep(inventoryService, order),
new ProcessPaymentStep(paymentService, order)
);

SagaTransaction saga = new SagaTransaction(steps);

try {
saga.execute();
log.info("Saga事务执行成功");
} catch (Exception e) {
log.error("Saga事务执行失败,开始补偿", e);
saga.compensate();
}
}
}

/**
* Saga步骤接口
*/
public interface SagaStep {
void execute() throws Exception;
void compensate() throws Exception;
}

/**
* 创建订单步骤
*/
public class CreateOrderStep implements SagaStep {

private final OrderService orderService;
private final Order order;

public CreateOrderStep(OrderService orderService, Order order) {
this.orderService = orderService;
this.order = order;
}

@Override
public void execute() throws Exception {
orderService.createOrder(order);
}

@Override
public void compensate() throws Exception {
orderService.cancelOrder(order.getId());
}
}

/**
* 扣减库存步骤
*/
public class ReduceInventoryStep implements SagaStep {

private final InventoryService inventoryService;
private final Order order;

public ReduceInventoryStep(InventoryService inventoryService, Order order) {
this.inventoryService = inventoryService;
this.order = order;
}

@Override
public void execute() throws Exception {
inventoryService.reduceStock(order.getProductId(), order.getQuantity());
}

@Override
public void compensate() throws Exception {
inventoryService.addStock(order.getProductId(), order.getQuantity());
}
}

/**
* Saga事务管理器
*/
public class SagaTransaction {

private final List<SagaStep> steps;
private final List<SagaStep> executedSteps = new ArrayList<>();

public SagaTransaction(List<SagaStep> steps) {
this.steps = steps;
}

public void execute() throws Exception {
for (SagaStep step : steps) {
try {
step.execute();
executedSteps.add(step);
} catch (Exception e) {
throw new SagaExecutionException("Saga步骤执行失败", e);
}
}
}

public void compensate() {
// 逆序补偿
for (int i = executedSteps.size() - 1; i >= 0; i--) {
try {
executedSteps.get(i).compensate();
} catch (Exception e) {
log.error("补偿操作失败", e);
}
}
}
}

# 事务监控与性能优化

# 事务监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* 事务监控切面
*/
@Aspect
@Component
@Slf4j
public class TransactionMonitorAspect {

@Autowired
private MeterRegistry meterRegistry;

/**
* 监控所有事务方法
*/
@Around("@annotation(org.springframework.transaction.annotation.Transactional)")
public Object monitorTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();

Timer.Sample sample = Timer.start(meterRegistry);

try {
Object result = joinPoint.proceed();

// 记录成功指标
meterRegistry.counter("transaction.success", "method", methodName).increment();

return result;
} catch (Exception e) {
// 记录失败指标
meterRegistry.counter("transaction.failure", "method", methodName,
"exception", e.getClass().getSimpleName()).increment();
throw e;
} finally {
sample.stop(Timer.builder("transaction.duration")
.tag("method", methodName)
.register(meterRegistry));
}
}
}

/**
* 事务性能分析服务
*/
@Service
@Slf4j
public class TransactionPerformanceService {

@Autowired
private TransactionTemplate transactionTemplate;

/**
* 批量操作优化
*/
public void batchInsertOptimization(List<Order> orders) {
// ❌ 错误方式:在循环中开启事务
for (Order order : orders) {
transactionTemplate.execute(status -> {
orderRepository.save(order);
return null;
});
}

// ✅ 正确方式:批量操作在一个事务中
transactionTemplate.execute(status -> {
for (Order order : orders) {
orderRepository.save(order);
}
return null;
});
}

/**
* 长事务拆分
*/
public void longTransactionSplitting(List<Order> orders) {
int batchSize = 100;

for (int i = 0; i < orders.size(); i += batchSize) {
int endIndex = Math.min(i + batchSize, orders.size());
List<Order> batch = orders.subList(i, endIndex);

processBatch(batch);
}
}

@Transactional(timeout = 30) // 设置合理的超时时间
public void processBatch(List<Order> orders) {
for (Order order : orders) {
processOrder(order);
}
}

private void processOrder(Order order) {
// 处理单个订单
}

@Autowired
private OrderRepository orderRepository;
}

# 事务最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* 事务最佳实践示例
*/
@Service
@Slf4j
public class TransactionBestPractices {

/**
* 实践1:事务粒度要适当
*/
@Transactional
public void appropriateGranularity(Order order) {
// ✅ 将相关的操作放在一个事务中
orderRepository.save(order);
inventoryRepository.reduceStock(order.getProductId(), order.getQuantity());
orderLogRepository.insertLog(order.getId(), "订单创建");

// ❌ 不要将不相关的操作放在同一个事务中
// sendNotification(order); // 发送通知可以异步进行
}

/**
* 实践2:只读事务优化
*/
@Transactional(readOnly = true)
public List<Order> queryOrders(OrderQueryCondition condition) {
// 只读事务可以进行优化
return orderRepository.findByCondition(condition);
}

/**
* 实践3:合理设置超时时间
*/
@Transactional(timeout = 60) // 根据业务复杂度设置
public void complexBusinessOperation() {
// 复杂业务逻辑
}

/**
* 实践4:异常处理要明确
*/
@Transactional(rollbackFor = BusinessException.class)
public void explicitExceptionHandling() {
if (invalidCondition()) {
throw new BusinessException("业务异常,明确回滚");
}
}

/**
* 实践5:避免在事务中进行耗时操作
*/
@Transactional
public void avoidTimeConsumingOperations(Order order) {
// ✅ 数据库操作
orderRepository.save(order);

// ❌ 避免在事务中进行网络调用、文件IO等耗时操作
// externalApiCall(order);
// fileWrite(order);

// ✅ 可以在事务完成后进行
// TransactionSynchronizationManager.registerSynchronization(
// new TransactionSynchronization() {
// @Override
// public void afterCommit() {
// externalApiCall(order);
// }
// });
}

private boolean invalidCondition() {
return false;
}

@Autowired
private OrderRepository orderRepository;

@Autowired
private InventoryRepository inventoryRepository;

@Autowired
private OrderLogRepository orderLogRepository;
}

# 总结:事务管理的智慧

Spring 事务管理是一个看似简单但实则复杂的主题。通过这篇文章,我们深入探讨了:

  1. 理论基础:ACID 特性和隔离级别是理解事务的基础
  2. 核心机制:PlatformTransactionManager 和事务传播行为是 Spring 事务的核心
  3. 实战技巧:声明式事务的使用和常见问题的解决
  4. 高级应用:分布式事务和性能优化

在我的开发经验中,事务管理的最佳实践可以总结为:

  • 理解业务需求:不是所有操作都需要事务,要根据业务场景合理选择
  • 控制事务边界:事务粒度要适当,既不能太大也不能太小
  • 处理异常情况:明确哪些异常需要回滚,哪些不需要
  • 监控事务性能:及时发现和解决长事务问题
  • 测试事务逻辑:确保事务在各种异常情况下都能正确工作