城乡建设杂志官方网站,高端网站设计百家号,三河做网站,django做网站转载自 数据库 - 事务管理#xff08;ACID#xff09;隔离级别 事务传播行为
总览#xff1a; 事务的4大特性#xff08;ACID)
原子性#xff08;Atomicity#xff09; 原子性是指事务包含的所有操作要么全部成功#xff0c;要么全部失败回滚#xff0c;这和前…转载自 数据库 - 事务管理ACID隔离级别 事务传播行为
总览 事务的4大特性ACID)
原子性Atomicity 原子性是指事务包含的所有操作要么全部成功要么全部失败回滚这和前面两篇博客介绍事务的功能是一样的概念因此事务的操作如果成功就必须要完全应用到数据库如果操作失败则不能对数据库有任何影响。一致性Consistency 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态也就是说一个事务执行之前和执行之后都必须处于一致性状态。 拿转账来说假设用户A和用户B两者的钱加起来一共是5000那么不管A和B之间如何转账转几次账事务结束后两个用户的钱相加起来应该还得是5000这就是事务的一致性。隔离性Isolation 隔离性是当多个用户并发访问数据库时比如操作同一张表时数据库为每一个用户开启的事务不能被其他事务的操作所干扰多个并发事务之间要相互隔离。 即要达到这么一种效果对于任意两个并发的事务T1和T2在事务T1看来T2要么在T1开始之前就已经结束要么在T1结束之后才开始这样每个事务都感觉不到有其他事务在并发地执行。 关于事务的隔离性数据库提供了多种隔离级别稍后会介绍到。持久性Durability 持久性是指一个事务一旦被提交了那么对数据库中的数据的改变就是永久性的即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
事务并发访问的问题隔离性
脏读 两个事务正在并发的执行事实上最后结果应该是1500才对时间5时刻的查询余额为0就是脏数据事务A读取了事务B中未提交的数据这就是脏读。
时间事务A事务B1开始事务-2-开始事务3-查询余额有10004-取出1000余额05查询余额0-6-撤销掉事务7存入500余额500-8提交事务-
不可重复读 两个事务正在并发的执行结果A两次读取的结果不一样这是因为两次查询有间隔期间被其他事务修改并提交了事务相比脏读的区别是不可重复读是读取另一事务提交的数据。这种现象也是正常的是由于事务的隔离级造成的但是在在某些特别的情况下也是不允许的。
时间事务A事务B1开始事务-2-开始事务3-查询余额有10004查询余额1000-5 取出1000余额06-提交事务7查询余额0-
幻读 两个事务正在并发的执行事务A第一次统计和第二统计的结果不一样是因为事务B新增了一条数据和不可重复读一样都是读取了另外一个事务的数据不同的是不可重复读查询的是同一条数据而幻读则是针对批量的数据或者说不可重复读是A读取了B的更新数据幻读是A读取了B的新增数据。
时间事务A事务B1开始事务-2-开始事务3统计总金额10000-4--5 存入1006-提交事务7统计总金额10100-
数据库的隔离级别MySQL为例
明白上面的问题之后就明白为什么需要隔离级别了不同的隔离级别能处理不同的并发事务问题下表
事务级别脏读不可重复读幻觉读READ_UNCOMMITTED允许允许允许READ_COMMITTED禁止允许允许REPEATABLE_READ禁止禁止允许SERIALIZABLE禁止禁止禁止
MySQL默认的事务级别是READ_COMMITTED
JDBC的数据隔离级别设置
JDBC 访问TRANSACTION_READ_UNCOMMITTEDur就是俗称“脏读”dirty read在没有提交数据时能够读到已经更新的数据TRANSACTION_READ_COMMITTEDcs在一个事务中进行查询时允许读取提交前的数据数据提交后当前查询就可以读取到数据。update数据时候并不锁住表TRANSACTION_REPEATABLE_READrs在一个事务中进行查询时不允许读取其他事务update的数据允许读取到其他事务提交的新增数据TRANSACTION_SERIALIZABLErr在一个事务中进行查询时不允许任何对这个查询表的数据修改。
Spring的事务传播行为
事务传播
事务怎么传播方法A传播到方法B。 Spring解决的就是方法之间的事务传播。 下面看下每一种行为具体代表的含义
REQUIRED
业务方法需要在一个事务中运行。如果方法运行时已经处在一个事务中那么这个时候就会加入到该事务中如果当前没有事务环境的话就会为自己创建一个新的事务。
SUPPORTS
这一事务属性表明如果业务方法A在某个事务范围内被调用则方法成为事务的一部分。如果业务方法在事务范围外被调用则方法在没有事务的环境下执行。即当标注了事务传播属性——SUPPORTS的业务方法在另一个bean的业务方法中执行时如果另一个bean的业务方法开启了事务它就会处在事务中执行如果另一个bean的业务方法也没开启事务那么它也在没有事务的环境中进行。
MANDATORY
该属性指定业务方法只能在一个已经存在的事务中执行业务方法不能发起自己的事务。如果业务方法在没有事务的环境下调用容器就会抛出异常。一种比较强硬的方式。
REQUIRES_NEW
该属性表明不管当前是否存在事务业务方法总会为自己发起一个新的事务。如果方法已经运行在一个事务中则原有事务会被挂起新的事务会被创建直到方法执行结束新事务才算结束原先的事务才会恢复执行。
NOT_SUPPORTED
声明方法不需要事务。如果方法没有关联到一个事务容器不会为它开启事务。如果方法在一个事务中被调用(在其他业务bean的方法中被调用了而其他业务bean的方法是开启了事务的)该事务会被挂起在方法调用结束后原先的事务便会恢复执行。
NEVER
指定业务方法绝对不能在事务范围内执行。如果业务方法在某个事务中执行容器会抛出异常只有业务方法没有关联到任何事务才能正常执行。比较强硬的方式就是不支持事务。
NESTED
嵌套事务如果一个活动的事务存在则当前方法运行在一个嵌套的事务中。 如果没有活动事务就创建一个新的事务。它使用了一个单独的事务这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。外部事务回滚会导致内部事务的回滚。如果被调用的内部方法没有捕获异常跑出异常也会导致外部事务的回滚。
看下Spring中枚举定义的7种事务传播行为
package org.springframework.transaction.annotation;public enum Propagation {REQUIRED(0),SUPPORTS(1),MANDATORY(2),REQUIRES_NEW(3),NOT_SUPPORTED(4),NEVER(5),NESTED(6);private final int value;private Propagation(int value) {this.value value;}public int value() {return this.value;}
}
在使用注解方式的事务时候我们可以用下面的方式来设置事务的传播行为
Transactional(propagation Propagation.REQUIRED)
是不是很方便。
只读事务
readOnly属性设置为只读事务对于只读事务它就不能进行更新操作一般只存在数据读取的时候可以将readOnly属性设置为true可提供效率。
事务超时
timeout属性代表事务的超时时间默认为30s一般情况下都不需要设置超时时间。如果超过时间就回滚。