`
pouyang
  • 浏览: 313331 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring 事务管理-2

阅读更多
接 Spring 事务管理-1

1--在Spring中编写事务


public void method(){
		transactionTemplate.execute(
				new TransactionCallback() {
					public Object doInTransaction(TransactionStatus ts) {
						try {
							...........
						}catch (Exception e) {
							ts.setRollbackOnly();
						}
						return null;
					}
				}
				);
	}




2--Spring声明式事务

spring里声明式事务是用事务参数来定义的。一个事务参数就是对事务策略应该如何应用到某个方法的一段描述。虽然spring提供了几种声明事务的机制,但是它们都是依靠5个参数
来控制如何管理事务策略。

<!-- 配置事务属性 -->     
        <property name="transactionAttributes">     
            <props>     
                <prop key="*">PROPAGATION,ISOLATION(可选),readOnly(可选),-Exception,+Exception(可选)</prop>   
            </props>     
        </property>   


1,事务的控制只能做到方法的级别。
2,所有的事务策略都是依靠5个参数来控制。
下面看看这5个参数

第一个 PROPAGATION

 --1 mandatory
  --2 nested
  --3 never  多用于测试
  --4 not_supported  多用于只读
  --5 required  最常用
  --6 required_new
  --7 supports
 (就像启动多个 pl/sql 一样)    


  第二个 Isolation(隔离级别) 
        1 隔离级别定义一个事务可能受其他并发事务活动影响的程度
       2 也可以想象为那个事务对于事务处理数据的自私程度
       
        为什么要用隔离级别,因为并发导致了很多问题:
      问题一Dirty read(脏读)
:--脏读发生在一个事务读取了被另一个事务改写但尚未提交的数据--如果这些在稍后被回滚了,那么第一个事务读取的数据就会是无效的
   这发生在两个事务当中,而oracle自身的事务默认隔离级别是read committed
   并发的话,这种情况在oracle默认的隔离级别应该不会发生
   (有个问题,oracle的隔离级别有几种,spring事务的隔离级别有5种,怎么对应起来呢?难道 oracle隔离级别+锁机制 == spring 事务隔离级别 (spring的隔离级别多于oracle的隔离级别)oracle的隔离级别read Committed,serializable与锁又有什么关系,有时间看下悲观锁和乐观锁 
    oracle的serializable
       1: 事务 1 serializable ,事务 2 readCommitted 事务2更新数据1未提交,事务1更新数据1处在等待状态
       如果事务2提交则事务1抱错无法连续访问事务边界
       如果事务2回滚则事务1更新操作可以执行
       2: 事务1 serializable, 事务2 插入一条数据未提交,事务1可以进行插入操作
          事务2提交,事务1不能读取到事务2插入的数据。

       说明serializable把那一行数据琐住了,如果行数据更改了,那么该事务就不能进行更改而readOnly事务可以进行更改
并发更新一条数据所采取的解决方案:
        1: 对事务采取serializable隔离机制
        2: 程序控制:多添加一个字段 例如加version字段每更新一次做+1的操作,每次更新的时候都进行比较也可以加日期字段,那就要取到ms了。)
 

  问题二Nonrepeatable read(不可重复读)              
 一个事务里面两次查询的结果都不同,由于另一并发事务在两次查询之间更新了数据(更新)


  问题三 Phantom reads (幻读)
当一个事务读取几行记录后,另一个并发事务插入了一些记录时,幻读就发生了,在后来的查询中,第一个事务就会发现一些原来没有的记录(插入)




为了解决这些问题引入的隔离机制


1--default  使用后端数据库默认的隔离级别   oracle好象有两种,read committed 和 serializable
             问阿南:oracle数据库的隔离级别

2--read_uncommitted  允许读取尚未提交的数据,可能导致脏读,幻读或不可重复读

3--read_committed   允许从已经提交的并发事务读取,可防止脏读,但幻读和不可重复读仍可能发生

4--repeatable_read 对相同字段多次读取是一样的,除非数据被当前事务本身改变,可防止脏读和不可重复读,但有可能发生欢读


5--serializable  完全服从ACID的隔离级别,确保不发生脏读,不可重复读和幻读,这在所以隔离级别中也是最慢的,因为它通常
                 是通过完全琐定当前事务所涉及的数据表来完成。



第三个 只读 

如果一个事务只对后端数据库执行读操作,那么该数据库就可能利用那个事务的只读特性,采取某些优化措施。
   通过把一个事务声明为只读,可以给后端数据库一个机会来应用那些它认为合适的优化措施。
   由于只读的优化措施是在一个事务启动由后端数据库实施的,因此,对于那些具有可能启动一个新事物的传播行为的
   方法来说,将事务声明为只读才有意义。
  
   此外,如果正在使用hibernate作为持久化机制,那么把一个事务声明为只读,将使Hibernate的flush模式被设置为
   FLUSH_NEVER,这就告诉Hibernate避免和数据库进行不必要的对象同步,从而把所有的更新延迟到事务的结束。


第四个 事务超时

   
可以设置在特定数秒后事务如果没有提交的话让他回滚


回滚规则

  
在默认设置下:事务只在出现运行异常(runtime exception)时回滚,而在出现受阻异常(checked exception)时不回滚
   在控制狂的设置下,就会变化的。






容器启动事务:

   1--insert一条数据
   2--commit;
   3--insert一条数据
   4--insert

容器提交事务
 
   1--不管发生了什么,1只有没错,1-insert永远插入
   2--如果三或者四发生了运行异常并且没有捕捉,则三四都回滚
   3--如果三或者四发生了运行异常且捕捉了,则若发生异常后面的全部回滚,发生异常前面的不回滚(注意:捕捉了!!)

  如果第三条语句出现问题,并且异常被捕捉到了
  则1--insert一条数据提交成功  ,commit 之后
  如果没有捕获到或者说没有做catch的操作,
  //只是在方法签名上做了throws动作,那么插入失败。
  则3--insert
 

这是我在ibatis情况下测试的,自己借助ibatis手动控制事务,

如果事务交给了spring容器管理,
会不会在 3-insert 处发生异常进行全部回滚。
1,经过测试不论发生什么情况:1都会执行,并插入到数据库中去。




sql异常 RuntimeException 捕获不到的,所以XX系统异常处理有问题

















      



      


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics