EJB 事务注意事项

在上篇文章我们提到,当运行多个事务的时候,并且这些事务方式数据库中的相同数据会出现一系列的并发问题,这些问题汇总起来总共有以下几类.

丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖。

 

脏读:一个事务读到另一个事务为提交的更新数据。

不可重复读:一个事务读到另一个事务已提交的更新数据。

幻像读:一个事务读到另一个事务已提交的新插入的数据。

       丢失更新

      当多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。  

举一个小例子来帮助进一步理解:当事务A和事务B同时修改数据库表的某行的值,

1.事务A将数值改为10000并提交

2.事务B将数值改为20000并提交。这时数据的值为20000,事务A所做的更新将会丢失。

解决办法:对行加锁,只允许并发一个更新事务。

       脏读

  当第二个事务选择其它事务正在更新的行时,会发生未确认的相关性问题。第二个事务正在读取的数据还没有确认并且可能由更新此行的事务所更改。

1.甲的原工资为10000, 乙将甲的工资改为了15000,此时但未提交事务.

2.甲读取自己的工资 ,发现自己的工资变为了15000!

3.而乙发现操作有误,回滚了事务,甲的工资又变为了10000 像这样,甲记取的工资数15000是一个脏数据。

    解决办法:如果在第一个事务提交前,任何其他事务不可读取其修改过的值,则可以避免该问题。

   非重复读

  当第二个事务多次访问同一行而且每次读取不同的数据时,会发生不一致的分析问题。不一致的分析与未确认的相关性类似,因为其它事务也是正在更改第二个事务正在读取的数据。然而,在不一致的分析中,第二个事务读取的数据是由已进行了更改的事务提交的。而且,不一致的分析涉及多次(两次或更多)读取同一行,而且每次信息都由其它事务更改;因而该行被非重复读取。

在一个事务中前后两次读取的结果并不致,导致了不可重复读。

1.在事务1中,甲读取了自己的工资为10000,操作并没有完成

2.在事务2中,这时乙修改了甲的工资为50000,并提交了事务.

3.在事务1中,甲再次读取自己的工资时,工资变为了50000

解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。

    幻像读     

  当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,因为该行已被其它事务删除。同样,由于其它事务的插入操作,事务的第二次或后续读显示有一行已不存在于原始读中。

目前工资为10000的员工有5人。

1.事务1,读取所有工资为10000的员工。

2.这时事务2向表插入了一条员工记录,工资也为10000

3.事务1再次读取所有工资为10000的员工共读取到了6条记录,

    解决办法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题。

          上面所产生的并发问题我们都基本上给出了解决的方案或者建议,也就是用锁.锁机制能有效地解决并发事务时的各种问题,但是也会影响到并发的性能。数据库系统提供了相应的解决方案,我们将在下一篇文章中来了解隔离级别.

 在上文中我们提到,锁机制能有效地解决并发事务时的各种问题,但是也会影响到并发的性能。数据库系统提供了4种可选的事务隔离级别,它们是

 

1.Read Uncommited:读未提交的数据

 

2.Read commited:读已提交的数据

 

3.Repeateble Read:可重复读

 

4.Serialable:序列化

 

 

ReadUncommited: 该隔离级别读取数据时不使用任何锁。可能会出现脏读,不可重复读,和虚读的问题。

 

Readcommited:返回的是读取时间点之前已提交的数据,因此可以避免脏读。但重复读数据时,返回的数据和读取时间点有关,因此会重现不可重复读,另外还会出现虚读现象。

 

RepeatableRead:该隔离级别能够保证重复读,可以避免脏读和不可重复读问题。

 

Serializable:该隔离级别能够避免脏读,不可重复读和虚读现象,是最严格的隔离级别。

 

        上面四种隔离级别,从1-4隔离级别越来越严格,数据安全和真实性越来越高,但并发性能越来越低。所以选择什么样的隔离级别应根据应用的具体要求而定。对于多数应用程序,可以有优先考虑把数据库系统的隔离级别设为ReadCommited,它能够避免脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻像读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

 

  A.悲观锁:指在应用程序中显示的为数据资源加锁。尽管能防止丢失更新和不可重复读这类并发问题,但是它会影响并发性能,因此应该谨慎地使用。

 

  B.乐观锁:乐观锁假定当前事务操作数据资源时,不会有其他事务同时访问该数据资源,因此完全依靠数据库的隔离级别来自动管理锁的工作。应用程序采用版本控制手段来避免可能出现的并发问题。

 

        至此我们对数据库事务的相关内容有了进一步了解,也为EJB的事务管理做了一系列的铺垫,在下一篇文章我们将具体来了解EJB是如何进行事务管理的.

转自http://blog.csdn.net/jnqqls/article/details/17040981

猜你喜欢

转载自xjl712.iteye.com/blog/2095080
EJB