Spring事务的隔离级别与传播机制

隔离级别可能引发的问题
脏读
● 一个事务读取了另一个事务未提交的数据(正在修改但尚未提交的数据),如果另一个事务回滚了(该数据在查询之后发生了回滚),该事务读取到的数据就是无效的
不可重复读
● 在同一个事务中,两次读取同一行,但由于其它事务的修改而读取到的不一样
● 场景:事务第一次读取后,另一个事务修改并提交了事务,第二次读取的时候与第一次不一致
幻读
● 同一事务中,在多次查询的过程中,其它事务添加或删除了符合条件的数据,导致查询结果集不一致
不可重复度与幻读的异同
● 相同点:不可重复读和幻读都是由于并发事务之间的交互引起的数据不一致性问题,都体现了事务隔离性的重要性。
● 不同点:
○ 触发条件:不可重复读是因为同一事务内部多次读取同一数据时,被其他事务修改;而幻读是由于同一事务内部多次范围查询时,其他事务插入了新数据。
○ 影响内容:不可重复读主要影响单行数据的读取一致性,而幻读则主要影响范围查询的结果一致性。
隔离级别可能产生的问题
隔离级别 脏读 (Dirty Read) 不可重复读 (Non-repeatable Read) 幻读 (Phantom Read)
READ UNCOMMITTED
读未提交 可能发生 可能发生 可能发生
READ COMMITTED
读已提交 不会发生 可能发生 可能发生
REPEATABLE READ
可重复读 不会发生 不会发生 可能发生
SERIALIZABLE
可串行化 不会发生 不会发生 不会发生
spring与数据库隔离级别的关系
Spring配置的隔离级别通常会覆盖数据库的默认隔离级别。也就是说,当你在Spring的@Transactional注解中指定一个隔离级别时,这个级别会影响事务的行为,而不是使用数据库的默认隔离级别。不过,如果数据库不支持你指定的隔离级别,Spring可能会回退到数据库支持的最高隔离级别。
MySQL事务隔离级别
MySQL支持四种事务隔离级别,每种级别控制了事务如何与其他事务交互,并影响数据的一致性和并发性能。以下是MySQL的事务隔离级别及其详细描述:

  1. READ UNCOMMITTED:
    ○ 特点:允许读取未提交的数据(脏读)。在这个隔离级别下,事务可以读取其他事务尚未提交的数据。
    ○ 优点:最低的隔离级别,性能最好。
    ○ 缺点:可能会导致脏读、不可重复读和幻读,数据一致性差。
    ○ 适用场景:适用于对数据一致性要求不高的场景。
  2. READ COMMITTED:
    ○ 特点:只允许读取已提交的数据。避免了脏读,但可能会发生不可重复读。
    ○ 优点:比READ UNCOMMITTED更高的隔离级别,避免了脏读。
    ○ 缺点:虽然避免了脏读,但在同一事务内读取的数据可能因其他事务的提交而有所不同(不可重复读)。
    ○ 适用场景:适用于对数据一致性有一定要求的场景。
  3. REPEATABLE READ:
    ○ 特点:保证在一个事务中多次读取相同的数据结果是一致的(避免不可重复读)。但在此级别下仍然可能会出现幻读。
    ○ 优点:避免了脏读和不可重复读。
    ○ 缺点:虽然防止了脏读和不可重复读,但不能完全解决幻读的问题。
    ○ 适用场景:这是MySQL的默认隔离级别,适用于大多数应用场景。
  4. SERIALIZABLE:
    ○ 特点:提供最高级别的隔离,确保事务串行执行。它通过对数据库行加锁来避免脏读、不可重复读和幻读。
    ○ 优点:最强的数据一致性保证。
    ○ 缺点:性能开销最大,可能会导致较低的并发性和更高的锁竞争。
    ○ 适用场景:适用于对数据一致性要求极高的场景。
    MySQL配置事务隔离级别
    在MySQL中,可以通过以下SQL命令来设置和查看当前会话或全局的事务隔离级别:
    ● 查看当前事务隔离级别:
    sqlSELECT @@tx_isolation;
    或在MySQL 8.0及以上版本中:
    sqlSELECT @@transaction_isolation;
    ● 设置会话级别的事务隔离级别:
    sqlSET SESSION TRANSACTION ISOLATION LEVEL ;
    例如,要设置为REPEATABLE READ:
    sqlSET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    ● 设置全局事务隔离级别:
    sqlSET GLOBAL TRANSACTION ISOLATION LEVEL ;
    例如,要设置为SERIALIZABLE:
    sqlSET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    注意:设置全局事务隔离级别需要有足够的权限,并且对所有新连接生效,而不会影响已经存在的连接。
    通过理解和配置这些事务隔离级别,你可以优化MySQL数据库在并发环境中的性能和数据一致性。
    spring事务隔离级别
  5. ISOLATION_DEFAULT:使用底层数据库的默认隔离级别。通常这取决于数据库的配置或管理系统。
  6. ISOLATION_READ_UNCOMMITTED:允许读取其他事务尚未提交的数据,可能会导致脏读(Dirty Read)。
  7. ISOLATION_READ_COMMITTED:只允许读取已提交的数据,防止脏读,但可能会发生不可重复读(Non-repeatable Read)。
  8. ISOLATION_REPEATABLE_READ:确保事务中所有的读取操作看到的是一致的数据,防止不可重复读,但可能会发生幻读(Phantom Read)。
  9. ISOLATION_SERIALIZABLE:提供最高级别的隔离,确保事务串行执行,避免脏读、不可重复读和幻读。它通常会导致性能开销较大。

spring事务传播机制
Spring的事务传播机制定义了一个事务方法如何与现有事务交互。当你在Spring中使用事务时,可以通过不同的传播行为来控制事务的传播方式。Spring提供了以下几种事务传播行为:

  1. REQUIRED(默认):如果存在一个事务,则加入该事务。如果没有事务,则创建一个新的事务。它保证在一个事务上下文中运行。
  2. REQUIRES_NEW:总是创建一个新的事务。如果已经存在一个事务,则挂起当前事务,直到新事务完成。新事务完成后,恢复挂起的事务。
  3. NESTED:在当前事务中创建一个嵌套事务。如果当前事务存在,则嵌套事务将在主事务内部运行,并且可以独立于主事务回滚。这个选项需要数据库支持保存点(Savepoint)机制。
  4. MANDATORY:必须在一个现有的事务中运行。如果没有事务,则抛出异常。
  5. SUPPORTS:如果存在一个事务,则加入该事务。如果没有事务,则以非事务方式执行。也就是说,方法可以在事务中执行,也可以不在事务中执行。
  6. NOT_SUPPORTED:总是以非事务方式执行。如果存在一个事务,则挂起当前事务,直到方法完成。
  7. NEVER:总是以非事务方式执行。如果存在一个事务,则抛出异常。
    传播机制的示例
    假设你有两个服务:ServiceA 和 ServiceB,并且 ServiceA 调用 ServiceB。根据不同的传播设置,这里是如何工作的:
    ● REQUIRED:如果 ServiceA 有事务,ServiceB 将加入这个事务。如果 ServiceA 没有事务,ServiceB 将创建一个新的事务。
    ● REQUIRES_NEW:即使 ServiceA 已经有事务,ServiceB 也会创建一个新的事务,并且 ServiceA 的事务会被挂起,等到 ServiceB 完成后再恢复 ServiceA 的事务。
    ● NESTED:如果 ServiceA 有事务,ServiceB 会在 ServiceA 的事务内部创建一个嵌套事务。ServiceB 的事务可以独立回滚而不会影响 ServiceA 的事务,前提是数据库支持保存点。
    ● MANDATORY:ServiceB 需要在 ServiceA 的事务中运行。如果 ServiceA 没有事务,ServiceB 将抛出异常。
    ● SUPPORTS:ServiceB 将在 ServiceA 的事务中运行,如果 ServiceA 有事务。如果 ServiceA 没有事务,则 ServiceB 将以非事务方式执行。
    ● NOT_SUPPORTED:ServiceB 总是以非事务方式执行。如果 ServiceA 有事务,ServiceB 将挂起 ServiceA 的事务,直到 ServiceB 完成。
    ● NEVER:ServiceB 不能在事务中运行。如果 ServiceA 有事务,ServiceB 将抛出异常。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值