• Spring事务管理


    事务简介:

    事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性

    事务就是一系列的动作,它们被当作一个单独的工作单元。这些动作要么全部完成,要么全部不起作用。

    事务的四个关键属性(ACID)

    ① 原子性(atomicity):事务室一个原子操作,有一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用
    ② 一致性(consistency):一旦所有事务动作完成,事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中
    ③ 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏
    ④ 持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中

    数据隔离级别  (未提交读,已提交读,可重复读,可串行化)


    SqlServer2008R2的默认隔离级别是“READ COMMITED”,MySQL的默认隔离级别是“REPEATABLE READ”。

    ·未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据

    ·提交读(Read Committed):只能读取到已经提交的数据。SQLServer,Oracle等多数数据库默认都是该级别 (不重复读)

    ·可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读

    ·串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

    事务并发问题:

    数据库事务并发带来的问题有:更新丢失、脏读、不可重复读、幻象读。假设张三办了一张招商银行卡,余额100元,分别说明上述情况。

    1.  第一更新丢失:两个事务对一行记录进行操作,事务A已提交,事务B提交发生异常,回滚,将记录返回到B操作前,抹掉了事务A的操作。

    1、第二更新丢失:一个事务的更新覆盖了另一个事务的更新。事务A:向银行卡存钱100元。事务B:向银行卡存钱200元。A和B同时读到银行卡的余额,分别更新余额,后提交的事务B覆盖了事务A的更新。更新丢失本质上是写操作的冲突,解决办法是一个一个地写。

    2、脏读:一个事务读取了另一个事务未提交的数据。事务A:张三妻子给张三转账100元。事务B:张三查询余额。事务A转账后(还未提交),事务B查询多了100元。事务A由于某种问题,比如超时,进行回滚。事务B查询到的数据是假数据。脏读本质上是读写操作的冲突,解决办法是写完之后再读。

    3、不可重复读:一个事务两次读取同一个数据,两次读取的数据不一致。事务A:张三妻子给张三转账100元。事务B:张三两次查询余额。事务B第一次查询余额,事务A还没有转账,第二次查询余额,事务A已经转账了,导致一个事务中,两次读取同一个数据,读取的数据不一致。不可重复读本质上是读写操作的冲突,解决办法是读完再写。

    4、幻象读:一个事务两次读取一个范围的记录,两次读取的记录数不一致。事务A:张三妻子两次查询张三有几张银行卡。事务B:张三新办一张银行卡。事务A第一次查询银行卡数的时候,张三还没有新办银行卡,第二次查询银行卡数的时候,张三已经新办了一张银行卡,导致两次读取的银行卡数不一样。幻象读本质上是读写操作的冲突,解决办法是读完再写。

    Spring事务:

    spring两种事物处理机制,一是声明式事物,二是编程式事物
    声明式事物
    1)Spring的声明式事务管理在底层是建立在AOP的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

    声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过等价的基于标注的方式),便可以将事务规则应用到业务逻辑中。因为事务管理本身就是一个典型的横切逻辑,正是AOP的用武之地。Spring开发团队也意识到了这一点,为声明式事务提供了简单而强大的支持。

    Spring强大的声明式事务管理功能,这主要得益于Spring依赖注入容器和Spring AOP的支持。依赖注入容器为声明式事务管理提供了基础设施,使得Bean对于Spring框架而言是可管理的;而Spring AOP则是声明式事务管理的直接实现者。

    和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

    编程式事务
    Spring的编程式事务即在代码中使用编程的方式进行事务处理,可以做到比声明式事务更细粒度。有两种方式一是使用TransactionManager,另外就是TransactionTemplate。

    事务的传播行为

    事务的传播行为可以由传播属性指定. Spring 定义了 7  种类传播行为

    事务注解方式: @Transactional

    事物传播行为介绍:
    @Transactional(propagation=Propagation.REQUIRED)
    如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
    @Transactional(propagation=Propagation.SUPPORTS)
    如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
    @Transactional(propagation=Propagation.NOT_SUPPORTED)
    容器不为这个方法开启事务
    @Transactional(propagation=Propagation.MANDATORY)
    必须在一个已有的事务中执行,否则抛出异常
    @Transactional(propagation=Propagation.NEVER)
    必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)

    事物超时设置:
    @Transactional(timeout=30) //默认是30秒

    事务隔离级别:
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    读取未提交数据(会出现脏读, 不可重复读) 基本不使用
    @Transactional(isolation = Isolation.READ_COMMITTED)
    读取已提交数据(会出现不可重复读和幻读)
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    可重复读(会出现幻读)
    @Transactional(isolation = Isolation.SERIALIZABLE)
    串行化

    MYSQL: 默认为REPEATABLE_READ级别
    SQLSERVER: 默认为READ_COMMITTED
     

    https://tech.meituan.com/innodb-lock.html

    https://www.jianshu.com/p/4e3edbedb9a8

    http://blog.csdn.net/pingnanlee/article/details/11488695

    http://www.mamicode.com/info-detail-1248286.html

    https://my.oschina.net/happyBKs/blog/513390

    http://www.kancloud.cn/evankaka/springlearning/119672

    http://www.cnblogs.com/hongdada/p/3392711.html

    http://blog.csdn.net/edward0830ly/article/details/8703123

    http://www.cnblogs.com/younggun/archive/2013/07/16/3193800.html

  • 相关阅读:
    腾讯2014 笔试
    iOS 并发编程之 Operation Queues
    iOS 架构
    loadView and viewDidLoad?
    Referring to weak self inside a nested block
    Weakify和strongify探究
    iOS开发的最佳实践
    iOS 书籍
    Object-C非正式协议与正式协议的区别
    解决element-ui中el-menu组件作为vue-router模式在刷新页面后default-active属性与当前路由页面不一致问题的方法
  • 原文地址:https://www.cnblogs.com/hongdada/p/6526376.html
Copyright © 2020-2023  润新知