事务隔离级别&传播机制

事务的四个隔离级别:

首先要说下三个概念:脏读、不可重复读、幻读

  • 脏读(Dirty Read)。脏读是指一个事务读取了另一个事务未提交的数据,这种数据有可能在将来被回滚,导致读取的数据是无效的。
  • 不可重复读(Unrepeatable Read)。不可重复读是指在一个事务内,两次读取同一数据集合时,由于另一个事务的修改并提交了数据,导致第一次和第二次读取到的数据不一致。
  • 幻读(Phantom Read)。幻读是指在一个事务内,多次执行同一查询时,由于另一个事务插入了新的数据行或删除了符合查询条件的行,导致查询结果集的数量或内容发生变化,就像发生了幻觉一样。
隔离级别异常情况异常情况
读未提交脏读不可重复读幻读
读已提交不可重复读幻读
可重复读幻读
序列化

一、Read Uncommitted -- 读取未提交内容

  • 一个事务可以查看到未提交的内容

  • 常产生脏读问题(脏读:读取到其他事务未提交(执行)的内容)

对同一数据表开启A、B两个事务(A、B事务交叉) start transaction

A事务只查询数据表中内容,B事务做增删改操作但不commit(提交)

A事务依旧可以查询到表中的数据改变(查询到未提交的内容--脏读)

二、Read Committed -- 读取提交内容

  • 一个事务只能查看已提交的内容

  • 常产生不可重复读的问题(不可重复读:同一事务中执行相同的select语句得到(修改)不同的结果)

对同一数据表开启A、B两个事务(A、B事务交叉) start transaction

A事务只查询数据表中内容,B事务做增删改操作但不commit(提交)

A事务查询不到表中的数据改变的内容

B事务提交

A查到的数据改变(A两次查询,产生不同的结果--不可重复读)

三、Repeatable Read -- 可重读

  • 同一事务的多个实例并发读取数据时得到同一结果

  • MySQL的默认事务隔离级别

  • 常产生幻读问题(幻读:多次读取时产生不同结果(插入或删除))

对同一数据表开启A、B两个事务(A、B事务交叉) start transaction

A事务只查询数据表中内容,B事务做增删改操作但不commit(提交)

A事务查询不到表中的数据改变的内容

B事务提交

A事务查询不到表中的数据改变的内容

A提交

A可查询到表中数据的改变

四、Serializable -- 可串行化

  • 最高隔离级别

  • 给事务加上共享锁,同时只能有一个事务操作,解决幻读问题

  • 会导致大量超时和锁竞争问题

开启A事务

开启B事务时无法增删该操作

Spring的的七种事务传播机制:

一、 REQUIRED

REQUIRED是默认的事务传播行为。如果当前存在事务,那么该方法将会在该事务中运行;如果当前没有事务,那么它会启动一个新的事务。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
 
    // 使用REQUIRED传播机制
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 方法A的业务代码...
        // 调用方法B
        serviceB.methodB();
        // 如果methodB出现错误,那么methodA和methodB的操作都会回滚。
    }
}
 
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // 方法B的业务代码...
    }
}


二、 SUPPORTS


如果当前存在事务,那么该方法将会在该事务中运行;如果当前没有事务,那么它可以以非事务方式执行。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
 
    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodA() {
        // 方法A的业务代码...
        serviceB.methodB();
        // 无论methodB是否出现错误,methodA的操作都不会回滚。
    }
}
 
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        // 方法B的业务代码...
    }
}

三、 MANDATORY

MANDATORY传播行为要求方法必须在一个现有的事务中执行,如果没有事务就抛出异常。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
 
    @Transactional(propagation = Propagation.MANDATORY)
    public void methodA() {
        // 方法A的业务代码...
        serviceB.methodB();
        // 如果没有现有事务,会抛出异常。
    }
}
 
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.MANDATORY)
    public void methodB() {
        // 方法B的业务代码...
    }
}

四、 REQUIRES_NEW

REQUIRES_NEW传播行为总是会启动一个新的事务。如果有一个事务正在运行,那么这个事务将会被挂起。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
 
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodA() {
        // 方法A的业务代码...
        serviceB.methodB();
        // methodB在新的事务中运行,无论是否出错,都不会影响methodA的事务。
    }
}
 
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
       public void methodB() {
        // 方法B的业务代码...
    }
}

五、 NOT_SUPPORTED


NOT_SUPPORTED传播行为总是以非事务方式执行,如果有一个事务正在运行,那么这个事务将会被挂起。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
 
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodA() {
        // 方法A的业务代码...
        serviceB.methodB();
        // 无论methodB是否出错,methodA的操作都不会回滚,因为它们不在同一个事务中。
    }
}
 
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodB() {
        // 方法B的业务代码...
    }
}

六、 NEVER


NEVER传播行为要求方法以非事务方式执行,如果有一个事务正在运行,将会抛出异常。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
 
    @Transactional(propagation = Propagation.NEVER)
    public void methodA() {
        // 方法A的业务代码...
        serviceB.methodB();
        // 如果有事务正在运行,会抛出异常。
    }
}
 
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.NEVER)
    public void methodB() {
        // 方法B的业务代码...
    }
}

七、 NESTED


NESTED传播行为在一个嵌套事务中执行,如果一个事务正在运行,那么它将在一个嵌套事务中执行。这个嵌套事务是可以独立提交或回滚的。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
 
    @Transactional(propagation = Propagation.NESTED)
    public void methodA() {
        // 方法A的业务代码...
        serviceB.methodB();
        // methodB在嵌套事务中运行,如果出错,只有嵌套事务会回滚,不会影响methodA的事务。
    }
}
 
@Service
public class ServiceB {
    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        // 方法B的业务代码...
    }
}

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
事务隔离级别是指多个事务并发执行时,一个事务对其他事务的可见性和影响程度的控制。Spring框架支持四个事务隔离级别: 1. 未提交读(READ UNCOMMITTED):最低级别,一个事务可以读取未提交的数据,会导致脏读,不可重复读和幻读问题的出现。 2. 提交读(READ COMMITTED):一个事务只能读取已提交的数据,可以避免脏读问题,但可能导致不可重复读和幻读问题。 3. 可重复读(REPEATABLE READ):在一个事务中多次读取同一数据时,结果保持一致,避免了不可重复读问题。但仍然可能存在幻读问题。 4. 串行化(SERIALIZABLE):最高级别,通过确保事务串行执行来避免脏读、不可重复读和幻读问题。但会降低并发性能。 传播机制是指在调用多个事务方法时,如何处理事务传播。Spring框架提供七种传播行为: 1. REQUIRED:如果当前没有事务,就创建一个新事务;如果已存在事务,则加入该事务。 2. SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方法执行。 3. MANDATORY:强制要求存在当前事务,如果没有事务就抛出异常。 4. REQUIRES_NEW:创建一个新事务,并暂停当前事务(如果有)。 5. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将其挂起。 6. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。 7. NESTED:在当前事务的控制下执行一个嵌套事务,如果不存在当前事务,则创建一个新事务。嵌套事务可以独立提交或回滚,但在外部事务提交时才会生效。 通过选择合适的事务隔离级别传播机制,可以确保事务的数据一致性、安全性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值