栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

总结篇 | 详聊事务

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

总结篇 | 详聊事务

本文介绍事务相关的概念,在数据库、spring中的事务及管理,以及分布式事务的解决方案,还有部分内容需要细化。

事务

数据库事务

事务定义并发事务会带来哪些问题事务隔离级别事务的实现原理

MVCC 实现原理readView 读取 Spring事务

1、Spring编程式事务2、Spring声明式事务Spring事务失效问题事务传播行为Spring事务实现原理Spring事务常见失效问题

1. 数据库存储引擎不支持。2. 没有被spring 管理3. 方法不是 public 的4. 自身调用问题5. 异常被吃了6. 异常类型错误 分布式事务

问题及解决方案

理论总体方案分布式事务解决方案详解

数据库事务 事务定义

定义:数据库系统中一系列操作的逻辑单元,所有操作要么全部成功要么全部失败
事务特性(ACID):

原子性(atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用。一致性(consistency):从一个一致性状态变换到另一个一致性状态,即一个事务执行之前和执行之后都必须处于一致性状态。隔离性(isolation):数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。持久性(durability):一个事务一旦被提交,则对数据库的所有更新将被保存到数据库中,不能回滚。 并发事务会带来哪些问题

在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一 数据进行操作)。并发虽然是必须的,但可能会导致以下的问题:

更新丢失: 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。脏读: 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。不可重复读: 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。幻读:幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。

并发事务带来很多问题,为了不同程度上避免这些问题,数据库设置了不同的事务合理级别。

事务隔离级别

读未提交 Read uncommitted :能够读取到没有被提交的数据。
读已提交 Read committed:即能够读到那些已经提交的数据。
可重复读 Repeatable read:读取了一条数据,这个事务不结束,别的事务就不可以改这条记录。
序列化Serializable:最高的事务隔离级别,不管多少事务,序列化执行
Spring事务

这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

√: 可能出现 ×: 不会出现

事务的实现原理

ACID中的AID都是为了实现C的。事务的最终目的就是为了实现“一致性”。
在MySQL里:
原子性:undolog ,通过undolog保证,如果失败可以回滚
隔离性:MVCC,多版本并发控制
持久性:redolog,(两阶段提交,WAL Write ahead log,先写日志再写数据)

MVCC 实现原理

// TODO

readView 读取

// TODO

Spring事务 1、Spring编程式事务 2、Spring声明式事务Spring事务失效问题

Spring 的声明式事务管理是建立在 Spring AOP 机制之上的,其本质是对目标方法前后进行拦截,并在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务

基于 命名空间的声明式事务管理
Spring 2.x 引入了 命名空间,结合使用 命名空间,带给开发人员配置声明式事务的全新体验,配置变得更加简单和灵活。总的来说,开发者只需基于和命名空间在XML中进行简答配置便可实现声明式事务管理。基于 @Transactional 的声明式事务管理  
除了基于命名空间的事务配置方式,Spring 还引入了基于 Annotation 的方式,具体主要涉及@Transactional 标注。@Transactional 可以作用于接口、接口方法、类以及类方法上:当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性;当作用于方法上时,该标注来覆盖类级别的定义。 事务传播行为

所谓spring事务的传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。

Spring事务实现原理

//TODO:详细补充
1.PlatformTransactionManager:平台事务管理器,主要是用于管理事务。
2.TransactionDefinition :事务定义的对象,该对象中定义了一系列基本的事务属性,并提供了获取事务相关的信息的方法。
3.TransactionStatus:事务的状态,它描叙了某一时间点上事务的状态信息。

Spring事务常见失效问题 1. 数据库存储引擎不支持。
 mySQL的myISAM存储引擎就不支持事务功能。
2. 没有被spring 管理

如下面例子所示:

// @Service
public class OrderServiceImpl implements OrderService {
    @Transactional
    public void updateOrder(Order order) {
        // update order
    }
}

如果此时把 @Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。

3. 方法不是 public 的

以下来自 Spring 官方文档:

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

大概意思就是 @Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。

4. 自身调用问题

来看两个示例:

@Service
public class OrderServiceImpl implements OrderService {

    public void update(Order order) {
        updateOrder(order);
    }

    @Transactional
    public void updateOrder(Order order) {
        // update order
    }

}

update方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?
再来看下面这个例子:

@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void update(Order order) {
        updateOrder(order);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateOrder(Order order) {
        // update order
    }

}

这次在 update 方法上加了 @Transactional,updateOrder 加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?

这两个例子都是:不管用

因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。有办法么,也有,大家可以自行查阅相关的解决办法。

5. 异常被吃了
// @Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
            // update order
        } catch {

        }
    }

}
6. 异常类型错误
// @Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
            // update order
        } catch {
            throw new Exception("更新错误");
        }
    }
}

这样事务也是不生效的,因为默认回滚的是:RuntimeException,如果你想触发其他异常的回滚,需要在注解上配置一下,如:

@Transactional(rollbackFor = Exception.class)
这个配置仅限于 Throwable 异常类及其子类。

分布式事务

分布式事务场景:一个服务一个数据库,比如:用户服务对应一个用户数据库,商品服务对应一个商品数据库,订单服务对应一个订单数据库,这就是微服务的产生,微服务之间通过远程调用完成事务操作,这就产生了分布式事务。

问题及解决方案 理论

在分布式系统中,难免会出现网络以及服务故障等,如果保证分布式系统的事务。通常情况下为达到良好的响应性能提升用户体验,通常会选择CAP理论中AP组合,舍弃C强一致性,保证最终一致性。首先来回顾一下CAP 理论:

CAP:指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)可用性(A):保证每个请求不管成功或者失败都有响应。分区容忍性(P):系统中任意信息的丢失或失败不会影响系统的继续运作。 总体方案

分布式事务解决方案详解

// TODO详解及线上应用案例

说明:本文是在总结过程,参考很多个人分享以及网上资料进行整理汇总整理。链接比较零碎,不一一列举了。如侵删。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781618.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号