spring事务理解

分布式事务中是否可以有加锁解锁的逻辑?可以,但是不规范的话会有线程安全问题。
下方逻辑:在解锁后,并发线程会再执行一遍锁里的逻辑,因为此时事务未提交,在隔离级别不是read uncommited的情况下,都读取不到原线程insert的数据,所以并发线程会再次insert数据;
这种情况是对于线程执行的原子性进行了割裂;
解决:对事务进行加锁,而不是放到内层;但是因为在加锁与解锁的过程中,中间事务的逻辑耗时大的话,会导致获取锁失败的异常变多。
思考:修改操作会不会有问题?不会,因为数据库对修改就是加锁的,并且也就不用加锁;

public void method(){
    transactionTemplate.execute(new TransactionCallback<T>(){
       public T doInTransaction(TransactionStatus status){
           lock(){
               object = query();
               if(null == object){
					insert; 
               }
           }

           //解锁后逻辑
           ...

           return T;
       }
    });
}

spring声明式事务失效的场景

spring声明式事务失效的场景:(大部分是由于spring事务的机制,通过aop动态代理对方法重写,通过数据库连接来实现)

  1. 修饰符造成失效;
    a. 非public的权限修饰符,会直接返回null
    b. static静态修饰符
    c. final修饰符,导致不能被重写
  2. 事务方法被没有事务的方法调用;还是由于spring事务的机制;
    a. 在类中注入自己本身,并调用该事务方法;
    b.使用AopContext.currentProxy() 去获得对应的代理对象去调用事务方法;
  3. 类未被spring管理,即没有在容器中初始化类对象;注解 或xml配置;
  4. 多线程调用:新启了一个线程去调用事务方法,该事务方法回滚,外层事务不会回滚(因为内层事务即线程跟外层用的不是用一个数据库连接;)
  5. 数据库不支持事务:如MyISAM
  6. 未开启事务;
  7. 使用错了事务(配置的传播特性不适合当前场景)propagation属性
  8. 手动catch了异常,并未抛出;或者抛出的异常不是运行异常或者error;
  9. 事务设置的回滚异常 与 运行时抛出的异常不一致,导致不会滚;(通常设置的回滚异常应为:Exception或 Throwable)rollbackFor属性
  10. 嵌套事务回滚多了:内层事务回滚影响外层事务(可以对内层事务的调用处捕获异常,且不抛出)

spring事务传播行为

  • PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。
    • 声明式事务的默认传播行为;
  • PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
  • PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
  • PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
    • 外层事务回滚,对内层事务没有影响;内层事务是独立的事务
  • PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
  • PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
    解释:
  1. 嵌套事务:相当于父事务与子事务的概念;只有父事务提交了,子事务才会被提交;父事务回滚了,子事务也会回滚;

spring事务隔离级别

  • ISOLATION_DEFAULT -- 使用数据库默认的隔离级别,mysql为REPEATABLE_READ,oracle为READ_COMMITTED
  • ISOLATION_READ_UNCOMMITTED -- 最低的隔离级别,会出现脏读、不可重复读、幻读;
  • ISOLATION_READ_COMMITTED -- 会出现不可重复读,幻读;
  • ISOLATION_REPEATABLE_READ -- 会出现幻读;
  • ISOLATION_SERIALIZABLE -- 可串行化:最高的隔离级别,完全服从 ACID 的隔离级别。事务逐个执行,之间不会产生干扰;

spring事务超时时间

事务允许运行的最长时间,超过这个时间还没有执行完成,则会回滚;int类型,单位是s,默认值为-1;

spring事务只读属性

对于只有数据查询的事务,可以设置为只读属性;
问题:为什么全都是查询的逻辑还要加事务?

spring事务回滚规则

这些规则定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常(RuntimeException 的子类)时才会回滚,Error 也会导致事务回滚,但是,在遇到检查型(Checked)异常时不会回滚。

@Transactional

@Transactional注解中的属性在上面都已列出;

属性名 说明
propagation 事务的传播行为,默认值为 REQUIRED,可选的值在上面介绍过
isolation 事务的隔离级别,默认值采用 DEFAULT,可选的值在上面介绍过
timeout 事务的超时时间,默认值为-1(不会超时)。如果超过该时间限制但事务还没有完成,则自动回滚事务。
readOnly 指定事务是否为只读事务,默认值为 false。
rollbackFor 用于指定能够触发事务回滚的异常类型,并且可以指定多个异常类型。
posted @   lq-12040  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示