1. 定义

在软件开发领域, 全有或全无的操作被称为事务(transaction)事物允许将几个操作组合成一个要么全部发生要么全部不发生的工作单元。发生和不发生两者只能选择其一,而不可能两者都选择。事务确保了数据和资源免于处在不一致的状态。

让我们继续使用最简单有效的转账例子来说明事务:

A给B转100元,这个过程大概需要两步: step1、从A的账户扣除100元; step2、给B的账户增加100元。

这两步必须要么全部执行成功要么都不成功并且还原账户的金钱为初始值,否则转账失败。如果step1成功而step2失败,那么A账户少了100元,但是B却没收到钱;如果step1失败而step2成功,B账户会多出100元。这两种情况都是不允许发生的。

所以,step1和step2必须处于同一事务中,我们就说事务把这两个操作组合为要么都成功要么都失败的工作单元。整个操作成功,那么转账成功,结果是A账户扣了100元而B账户多了100元;如果整个过程失败,那么A和B的账户的金额恢复到转账前的状态,即未发生任何变化,就像转账操作从未发生过一样。

2. ACID特性

  • Atomic(原子性):确保所有操作要么都发生,要么都不发生。

  • Consistent(一致性):事务前后,数据均处于正确状态,数据不应该被破坏。

  • Isolated(隔离性):事务彼此隔离,用户间操作不相混淆。

  • Durable(持久性):事务一旦完成,结果应该持久化,例如保存到数据库中。

上边转账的例子中,两步操作必须要么成功要么都失败,确保了原子性;而原子性保证账户中的金额不会处于不一致或者说部分完成,保证了一致性;转账过程与其他转账过程互不影响,遵循隔离性;转账成功后,结果必须持久化保存,防止事务结果丢失。

3. Spring对事务管理的支持

Spring提供两者事务管理方式:编程式事务管理和声明式事务管理。

3.1. 编程式事务管理

编写程序式的事务管理可以清楚的定义事务的边界,可以 实现细粒度的事务控制,比如你可以通过程序代码来控制你的事务何时开始,何时结束等,与后面介绍的声明式事务管理相比,它可以实现细粒度的事务控制。

3.2. 声明式事务管理

如果你并不需要细粒度的事务控制,你可以使用声明式事务,在Spring中,你只需要在Spring配置文件中做一些配置,即可将操作纳入到事务管理中, 解除了和代码的耦合, 这是 对应用代码影响最小的选择,从这一点再次验证了Spring关于 AOP的概念。当你不需要事务管理的时候,可以直接从Spring配置文件中移除该设置。

Spring通过回调机制将实际的事务实现从事务性代码中抽象出来。如果应用只使用一种持久化资源,那么可以使用持久化机制本身的事务性支持(JDBC、Hibernate、JPA等);如果应用事务跨多个资源,那么Spring会使用第三方的JTA(JAVA事务API)实现来支持分布式(XA)事务。

使用声明式事务还是编程式事务管理,在很大程度上是 细粒度和易用性之间权衡。一般情况下,不需要精确控制事务,采用声明式事务不仅易用性高,而且降低了事务与其他业务代码的耦合性。

4. 总结

在软件开发领域,全有或全无的操作被称为事务。事务必须具备ACID特性,在Spring中,除了编程来精确控制事务,还可以使用AOP来配置低耦合度的声明式事务控制。


相关阅读