事务四大特性、隔离级别和传播特性

本文详细介绍了数据库事务的ACID特性,包括原子性、一致性、隔离性和持久性,并讲解了如何在Spring中使用@Transactional注解来管理事务。讨论了事务的隔离级别,如READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE,以及它们对并发问题的解决方案。此外,还阐述了事务的传播行为、超时设置、只读事务以及异常处理策略。最后,给出了不同业务场景下@Transactional注解的使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事务四大特性ACID

A 原子性:原子性指的是 在一组业务操作下 要么都成功 要么都失败

在一组增删改查的业务下 要么都提交 要么都回滚

C 一致性:事务前后的数据要保证数据的一致性

在一组的查询业务下 必须要保证前后关联数据的一致性

I 隔离性:在并发情况下 事物之间要相互隔离。

D 持久性:数据一旦保存就是持久性的。

@Transactional注解应该写在哪

@Transactional 可以标记在类上面(当前类所有的方法都运用上了事务)

@Transactional 标记在方法则只是当前方法运用事务

也可以类和方法上面同时都存在, 如果类和方法都存在@Transactional会以方法的为准。如果方法上面没有@Transactional会以类上面的为准

建议:@Transactional写在方法上面,控制粒度更细, 建议@Transactional写在业务逻辑层上,因为只有业务逻辑层才会有嵌套调用的情况。

事务配置的属性

isolation:设置事务的隔离级别

propagation:事务的传播行为

noRollbackFor:那些异常事务可以不回滚

noRollbackForClassName:填写的参数是全类名

rollbackFor:哪些异常事务需要回滚

rollbackForClassName:填写的参数是全类名

readOnly:设置事务是否为只读事务

timeout:事务超出指定执行时长后自动终止并回滚,单位是秒

设置隔离级别(isolation)

1、设置隔离级别(isolation)

用来解决并发事务所产生一些问题:

并发: 同一个时间,多个线程同时进行请求。

什么时候会生成并发问题:在并发情况下,对同一个数据(变量、对象)进行读写操作才会产生并发问题

并发会产生什么问题?

1.脏读

2.不可重复度

3.幻影读

概念: 通过设置隔离级别可解决在并发过程中产生的那些问题:

1.脏读

1. 一个事务,读取了另一个事务中没有提交的数据,会在本事务中产生的数据不一致的问题

解决方式:@Transactional(isolation = Isolation.READ_COMMITTED)

读已提交:READ COMMITTED

         要求Transaction01只能读取Transaction02已提交的修改。

2.不可重复读

一个事务中,多次读取相同的数据, 但是读取的结果不一样, 会在本事务中产生数据不一致的问题。

解决方式:@Transactional(isolation = Isolation.REPEATABLE_READ)

可重复读:REPEATABLE READ

         确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。(行锁)

3.幻影读

并发安全:SERIALIZABLE>REPEATABLE_READ>READ_COMMITTED

运行效率:READ_COMMITTED>REPEATABLE_READ>SERIALIZABLE

当不设置事务隔离级别将使用数据库的默认事务隔离级别:

#MYSQL:REPEATABLE-READ
SELECT @@tx_isolation;  
#ORACLE: READ_COMMITTED
SELECT s.sid, s.serial#,
  CASE BITAND(t.flag, POWER(2, 28))
    WHEN 0 THEN 'READ COMMITTED'
    ELSE 'SERIALIZABLE'
  END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');

 事务的传播特性

事务的传播特性指的是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行?
希望如果外部存在事务就用外部的, 外部不存在就自己开启事务

@Transactional
trans(){
sub();
log();    // 记录流水 数据库操作
add();
} 
@Transactional  REQUIRES_NEW
log();

 1、spring的事务传播行为:

变更:2021-08-04 用挂起这个词容易造成误解,直接说不用外部事务 更适当

SUPPORTS用在有查询功能的方法上。

2、超时属性(timeout)

指定事务等待的最长时间(秒)

当前事务访问数据时,有可能访问的数据被别的数据进行加锁的处理,那么此时事务就必须等待,如果等待时间过长给用户造成的体验感差。

 

3、设置事务只读(readOnly)

readonly:只会设置在查询的业务方法中

connection.setReadOnly(true) 通知数据库,当前数据库操作是只读,数据库就会对当前只读做相应优化

当将事务设置只读 就必须要你的业务方法里面有增删改。

如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;

如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持(如:设置不可重复度、幻影读级别)。

对于只读事务,可以指定事务类型为readonly,即只读事务。由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段

4、异常属性

设置 当前事务出现的那些异常就进行回滚或者提交。

默认对于RuntimeException 及其子类 采用的是回滚的策略。

默认对于Exception 及其子类 采用的是提交的策略。

1、设置哪些异常不回滚(noRollbackFor)

2、设置哪些异常回滚(rollbackFor )

@Transactional(timeout = 3,rollbackFor = {FileNotFoundException.class})

5、在实战中事务的使用方式

如果当前业务方法是一组 增、改、删 可以这样设置事务

@Transactional

如果当前业务方法是一组 查询 可以这样设置事务

@Transactionl(readOnly=true)

如果当前业务方法是单个 查询 可以这样设置事务

@Transactionl(propagation=propagation.SUPPORTS ,readOnly=true)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值