Spring 事务管理

1. 背景

本节学习在 Spring 框架中使用事务。

2.基础知识

数据库事务( Transaction):是指操作数据库的一组操作序列,它可能包含查询或者更新操作,这组操作在执行过程中是一个逻辑单位,要么一起成功,要么一起失败。

事务的基本概念

事务包含了一个序列的对数据库的读/写操作,具有以下特性::

  • 1、提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
  • 2、当多个应用程序并发访问时,要在这些应用程序之间提供一个隔离方法,防止互相干扰。
  • 3、当事务被提交给了数据库管理系统(DBMS),DBMS需要确保该事务中的所有操作都成功完成,且结果被永久保存。
  • 4、如果事务中有的操作没有成功完成,则事务中的所有操作都需要回滚,回到事务执行前的状态。

四大特性(ACID特性)

数据库事务拥有以下四个特性,习惯上被称之为ACID特性。

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

事务的过程

SQL国际标准 使用三个过程来描述事务:

  • 开始:使用START TRANSACTION开始一个事务(或者用 BEGIN TRANSACTION)。
  • 提交:COMMIT语句使事务成功完成。
  • 回滚:ROLLBACK语句结束事务,放弃从开始的一切变更。

3. Spring 的事务

3.1 Spring 事务管理的一组 API

Spring 使用 PlatformTransactionManager 类来管理事务,根据不同的数据访问框架提供不同的实现,主要有下面这些API:

类(Class) 说明
PlatformTransactionManager 事务管理器
TransactionDefinition 事务的定义信息,包括隔离级别,传播,超时时间设置等。
TransactionStatus 事务的运行时状态。

这三个类构成了 Spring 事务管理的主要内容,下面分别说明。

3.2 PlatformTransactionManager ( 事务管理器 )

PlatformTransactionManager 负责管理事务的开始,提交和回滚。

看下接口定义:

public interface PlatformTransactionManager extends TransactionManager {
    // 开始一个事务
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
    // 提交事务
    void commit(TransactionStatus var1) throws TransactionException;
    // 回滚事务
    void rollback(TransactionStatus var1) throws TransactionException;
}

Spring 可根据不同的数据访问框架选择不同的具体 事务管理器实现。

3.3 TransactionDefinition ( 事务的定义 )

TransactionDefinition 包含了事务的定义信息,包括隔离级别,传播,超时时间设置等

1、Spring 事务的隔离级别

事务在执行过程中要与其他事务隔离,不得影响其他事务的执行。由并发的的访问可能引发一系列的数据访问问题,Spring 的事务隔离级别定义了一些事务的隔离策略:

隔离级别 说明 解释
DEFAULT (默认) 默认级别 使用数据库自身默认的事务隔离级别
READ_UNCOMMITTED (读未提交) 允许读取到未提交的数据 允许其他事务读取到这个事务已修改而未提交的数据
READ_COMMITTED (读已提交) 允许读取已提交的数据 这个事务修改且提交后,才可用被其他事务读取到。
REPEATABLE_READ (可重复读) 允许多次读取相同字段时数据一致,期间字段不可被其他事务修改。 读取指定字段数据期间,其他事务不能修改这个数据。
SERIALIZABLE(串行化) 事务被处理成按顺序执行 按序列执行事务,即便新增记录的影响也是排队执行后发生。

2、事务产生的问题

脏读
当一个事务允许读取另外一个事务修改但未提交的数据时,就可能发生脏读(dirty reads)。

不可重复读
在一次事务中,当一行数据获取两遍得到不同的结果表示发生了不可重复读(non-repeatable reads).

幻读
在事务执行过程中,当两个完全相同的查询语句执行得到不同的结果集。这种现象称为“幻读(phantom read)”。幻读 强调的是结果集的数量不同。

3、不同的 隔离级别 应对 事务产生的问题

从下表可以看到,隔离级别越向下,可能发生的问题越少。不过性能也越来越低。

隔离级别 脏读 不可重复读 幻影读
READ_UNCOMMITTED 可能发生 可能发生 可能发生
READ_COMMITTED - 可能发生 可能发生
REPEATABLE_READ - - 可能发生
SERIALIZABLE - - -

4、在不同的隔离级别时 锁 的持续时间不同

在基于锁的并发控制中,隔离级别决定了锁的持有时间。如果锁在语句执行完毕就释放则另外一个事务就可以在这个事务提交前修改锁定的数据,从而造成混乱。

隔离级别 写操作 读操作
READ_UNCOMMITTED 持有锁到该语句完毕 持有锁到该语句完毕
READ_COMMITTED 持有锁到提交时 持有锁到该语句完毕
REPEATABLE_READ 持有锁到提交时 持有锁到提交时
SERIALIZABLE 持有锁到提交时 持有锁到提交时

5、Spring 事务的传播行为

Spring事务传播机制规定了事务方法和事务方法发生嵌套调用时事务如何进行传递。即:面对在已有事务中被调用后怎么处理自身的事务。

REQUIRED 支持当前事务,如果没有事务会创建一个新的事务
SUPPORTS 支持当前事务,如果没有事务的话以非事务方式执行
MANDATORY 支持当前事务,如果没有事务抛出异常
REQUIRES_NEW 创建一个新的事务并挂起当前事务
NOT_SUPPORTED 以非事务方式执行,如果当前存在事务则将当前事务挂起
NEVER 以非事务方式进行,如果存在事务则抛出异常
NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

6、 Spring 事务的其他特性

  • 超时事件:timeout
  • 是否只读:isReadOnly

3.4 TransactionStatus ( 事务的运行状态 )

TransactionStatus 类里描述了一些运行时事务的状态和方法。

它包含这些方法:

    boolean hasSavepoint();
     // 刷新
    void flush();
    boolean isNewTransaction();
    void setRollbackOnly();
    boolean isRollbackOnly();
    //是否结束
    boolean isCompleted();
    // 检查点 相关的操作:创建,回滚,释放
    Object createSavepoint() throws TransactionException;
    void rollbackToSavepoint(Object savepoint) throws TransactionException;
    void releaseSavepoint(Object savepoint) throws TransactionException;

4. 示例

4.1 以 编程 的方式使用事务

获得注入的 TransactionTemplate 实例,执行 execute 方法。

public class DemoDao {
    @Autowired
    TransactionTemplate transactionTemplate;


    public void method1() {
        transactionTemplate.execute(new TransactionCallback<Void>() {
            @Override
            public Void doInTransaction(TransactionStatus status) {
                // 在这里写 具体的数据库操作调用
                return null;
            }
        });
    }
}

4.2 以 注解 的方式使用事务

使用 @Transactional 注解 作用在方法上即可。

    @Transactional
    public void method2() {
        // 在这里写 具体的数据库操作调用
    }

5. 扩展

PlatformTransactionManager 的多种实现选择

前面说过,Srping 可根据不同的持久层框架可选择不同的的 事务管理器的实现,比如:

DataSourceTransactionManager JDBC 和 mybatis 时使用
JpaTransactionManager 使用 JPA 时使用
HibernateTransactionManager 使用 Hibernate 时使用
JtaTransactionManager 使用分布式事务 JTA 时使用

6.参考:

https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BA%8B%E5%8A%A1
https://www.imooc.com/video/9323
https://zh.wikipedia.org/wiki/%E4%BA%8B%E5%8B%99%E9%9A%94%E9%9B%A2

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容