并发事务 可能导致的问题

并发事务可能引起的事情:

1.脏读:

对于两个事务T1 和T2 , T1 读取了已经被T2 更新但还没有被提交的字段。之后,若T2 进行回滚,T1读取的内容就是临时且无效的

2.不可重复读:

对于两个事务T1 和T2 , T1 读取了一个字段,然后T2 更新了该字段。之后,T1再次读取同一个字段,值就不同了

3.幻读:

对于两个事务T1,T2,T1从表中都去了一个字段,然后T2在该表中插入了一些新的行,之后,如果T1再次读取同一个表,就会多出几行

---------------------------------------------------------------------分割线-------------------------------------------------------------------------------------------------------------------------

转自http://www.cnblogs.com/muhezi/p/4599654.html

另外,在使用spring的注解式事务管理时,对事务的传播行为和隔离级别可能有点不知所措,下边就详细的介绍下以备方便查阅。

事物注解方式: @Transactional

当标于类前时, 标示类中所有方法都进行事物处理 , 例子:

@Transactional public class TestServiceBean implements TestService {}

当类中某些方法不需要事物时:

@Transactional public class TestServiceBean implements TestService { private TestDao dao; public void setDao(TestDao dao) { this.dao = dao; } @Transactional(propagation =Propagation.NOT_SUPPORTED) public ListgetAll() { return null; } }

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

事物超时设置:
@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

脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 
后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读 : 一个事务读到另一个事务已提交的insert数据

@Transactional注解中常用参数说明


参 数 名 称


功 能 描 述


readOnly


该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true)


rollbackFor


该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:

指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

续表)


参 数 名 称


功 能 描 述


rollbackForClassName


该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:

指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")

指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})


noRollbackFor


该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:

指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})


noRollbackForClassName


该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:

指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException")

指定多个异常类名称:

@Transactional(noRollbackForClassName={"RuntimeException","Exception"})


propagation


该属性用于设置事务的传播行为,具体取值可参考表6-7。

例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)


isolation


该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置


timeout


该属性用于设置事务的超时秒数,默认值为-1表示永不超时

注意的几点:
1 @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.

2用 spring 事务管理器,由spring来负责数据库的打开,提交,回滚.默认遇到运行期例外(throw new RuntimeException("注释");)会回滚,即遇到不受检查(unchecked)的例外时回滚;而遇到需要捕获的例外(throw new Exception("注释");)不会回滚,即遇到受检查的例外(就是非运行时抛出的异常,编译器会检查到的异常叫受检查例外或说受检查异常)时,需我们指定方式来让事务回滚要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常}) .如果让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
如下:
@Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚
public void methodName() {
throw new Exception("注释");

}
@Transactional(noRollbackFor=Exception.class)//指定不回滚,遇到运行期例外(throw new RuntimeException("注释");)会回滚
public ItimDaoImpl getItemDaoImpl() {
throw new RuntimeException("注释");
}

3、@Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。

4、@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 元素的出现 开启 了事务行为。

5、Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。

时间: 2024-08-25 06:28:33

并发事务 可能导致的问题的相关文章

并发事务的丢失更新及数据锁机制

在事务的隔离级别内容中,能够了解到两个不同的事务在并发的时候可能会发生数据的影响.细心的话可以发现事务隔离级别章节中,脏读.不可重复读.幻读三个问题都是由事务A对数据进行修改.增加,事务B总是在做读操作.如果两事务都在对数据进行修改则会导致另外的问题:丢失更新.这是本博文所要叙述的主题,同时引出并发事务对数据修改的解决方案:锁机制. 1.丢失更新的定义及产生原因. 丢失更新就是两个不同的事务(或者Java程序线程)在某一时刻对同一数据进行读取后,先后进行修改.导致第一次操作数据丢失.可以用图表表

数据库并发事务控制 一:综述

并发控制是DBMS的关键技术 对数据库的操作都是在事务中进行的. 事务是指一组相互依赖的操作行为.事务中的操作是不可分割的工作单元,由一组在业务逻辑上相互依赖的SQL语句组成,有ACID特征. Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败. Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态. Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完

利用索引降低并发事务引起的锁【转】

时常,来自不同连接的线程会对同一张表进行读/更新操作,这种并发操作会导致阻塞,同时SQL Server会自动处理以防止脏读.然而,有种情景很常见,那就是每个连接要读/更新的行互相排斥,换句话说,就是各个连接读/更新的行没有交集.在这片文章中,将像大家展示如何恰当地使用索引来降低阻塞的发生,以便多个读/更新能够同时操作同一张表. 创建TEST表如下: SET ANSI_NULLS ON GO   SET QUOTED_IDENTIFIER ON GO   CREATE TABLE [dbo].[T

Spring 并发事务的探究

前言 在目前的软件架构中,不仅存在单独的数据库操作(一条SQL以内,还存在逻辑性的一组操作.而互联网软件系统最少不了的就是对共享资源的操作.比如热闹的集市,抢购的人群对同见商品的抢购由一位售货员来处理,这样虽然能保证买卖的正确进行,但是牺牲了效率,饱和的销售过程并不能高效处理所有的购买请求,最后打烊了部分顾客悻悻而归.而电脑的发明是让人类解放于这种低效的工作中,提高销售性能,比如抢购系统,秒杀系统等.而这种销售过程必然包含了检查库存.秒杀排队.校对商品信息.下单等一系列的组合操作,而一个交易过程

并发事务之丢失更新

7 并发事务问题之丢失更新 丢失更新:一个事务的更新被另一个事务的更新覆盖了: 时间点 事务1 事务2 t1? 开始事务 ? t2? ? 开始事务 t3? 查询pid=p1的记录结果为[pid=p1,pname=zhangSan,age=23,sex=male] ? t4 ? 查询pid=p1的记录结果为[pid=p1,pname=zhangSan,age=23,sex=male] t5? 修改age=24,其它保留原值,即: update person set pname='zhangSan'

SOA并不能解决高并发事务

传统SOA架构其实无法面对高并发事务. 这种方式不适合热点资源,也就是高并发场合. 虽然乐观锁短,但是容易产生脏数据. SOA是以服务这个方式对外提供功能,我们很显然喜欢在Service中加上JTA等事务,比如EJB的无态Bean或Spring的@Transaction标注都是激活这样的功能,这种方式实际是一种悲观事务,容易引起死锁,特别是在高并发情况下.

数据库并发事务控制四:postgresql数据库的锁机制二:表锁

在博文<数据库并发事务控制四:postgresql数据库的锁机制 > http://blog.csdn.net/beiigang/article/details/43302947 中后面提到: 常规锁机制可以参考pg的官方手册,章节和内容见下面 13.3. Explicit Locking http://www.postgresql.org/docs/9.4/static/explicit-locking.html 这节分为:表锁.行锁.页锁.死锁.Advisory锁(这个名字怎么翻译好???

SqlServer 并发事务(一):事务隔离级别

--查了当前数据库是事务隔离级别 DBCC USEROPTIONS 表初始内容: SELECT * FROM Test  Wherename='kk' id  name   info 1   kk      NULL [测试一:丢失更新] --事务1 begin tran select * from dbo.Test(nolock) where name = 'kk' waitfor delay '00:00:05' update T set info = 'A更改' from Test T(n

InnoDB并发事务

?目录 1.行锁:索引加锁 2.意向锁 3.间隙锁 4.MVCC机制 行锁 InnoDB通过多版本并发控制MVCC来支持事务 InnoDB的设计是为了在处理大数据量的时候得到最好的性能.InnoDB存储引擎维护了一个它自己的缓冲区,用来存储数据和索引.InnoDB将表和索引存储在一个表空间中,这个表空间可能由不同的文件组成.而MyISAM存储引擎的表中每个表都存在一个独立的文件里面. InnoDB事务模型是将传统的两阶段封锁协议同多版本数据库特性相结合.它采用加行级锁和查询不加锁. InnoDB