乐趣区

关于数据库:JDBC事物管理与事物隔离界别

Spring 事务配置的五种形式

前段时间对 Spring 的事务配置做了比拟深刻的钻研,在此之间对 Spring 的事务配置虽说也配置过,然而始终没有一个分明的意识。通过这次的学习察觉 Spring 的事务配置只有把思路理清,还是比拟好把握的。
   
总结如下:
  
  Spring 配置文件中对于事务配置总是由三个组成部分,别离是 DataSource、TransactionManager 和代理机制这三局部,无论哪种配置形式,个别变动的只是代理机制这部分。
   
DataSource、TransactionManager 这两局部只是会依据数据拜访形式有所变动,比方应用 Hibernate 进行数据拜访时,DataSource 理论为 SessionFactory,TransactionManager 的实现为 HibernateTransactionManager。
    具体如下图:

   依据代理机制的不同,总结了五种 Spring 事务的配置形式,配置文件如下:
 
   第一种形式:每个 Bean 都有一个代理

<? xml version="1.0" encoding="UTF-8" ?>  < beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:aop ="http://www.springframework.org/schema/aop"      xsi:schemaLocation ="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> < bean id ="sessionFactory"class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >  
        < property name ="configLocation" value ="classpath:hibernate.cfg.xml"   />  
        < property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration"   /> </ bean >  

    <!-- 定义事务管理器(申明式的事务)-->  
    < bean id ="transactionManager" class ="org.springframework.orm.hibernate3.HibernateTransactionManager" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean > <!-- 配置 DAO --> < bean id ="userDaoTarget" class ="com.bluesky.spring.dao.UserDaoImpl" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean > < bean id ="userDao"  
        class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >  
           <!-- 配置事务管理器 -->  
           < property name ="transactionManager" ref ="transactionManager"   />     
        < property name ="target" ref ="userDaoTarget"   />  
         < property name ="proxyInterfaces" value ="com.bluesky.spring.dao.GeneratorDao"   /> <!-- 配置事务属性 -->  
        < property name ="transactionAttributes" >  
            < props >  
                < prop key ="*" > PROPAGATION_REQUIRED </ prop > </ props >  
        </ property >  
    </ bean >    </ beans >

    第二种形式:所有 Bean 共享一个代理基类

<? xml version="1.0" encoding="UTF-8" ?>  < beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:aop ="http://www.springframework.org/schema/aop" xsi:schemaLocation ="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> < bean id ="sessionFactory"class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >  
        < property name ="configLocation" value ="classpath:hibernate.cfg.xml"   />  
        < property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration"   /> </ bean >  

    <!-- 定义事务管理器(申明式的事务)-->  
    < bean id ="transactionManager" class ="org.springframework.orm.hibernate3.HibernateTransactionManager" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean > < bean id ="transactionBase"  
            class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"  
            lazy-init ="true" abstract ="true" >  
        <!-- 配置事务管理器 -->  
        < property name ="transactionManager" ref ="transactionManager"   />  
        <!-- 配置事务属性 -->  
        < property name ="transactionAttributes" >  
            < props >  
                < prop key ="*" > PROPAGATION_REQUIRED </ prop >  
            </ props >  
        </ property >  
    </ bean >    

    <!-- 配置 DAO --> < bean id ="userDaoTarget" class ="com.bluesky.spring.dao.UserDaoImpl" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean > < bean id ="userDao" parent ="transactionBase"   >  
        < property name ="target" ref ="userDaoTarget"   />   
    </ bean >  </ beans >

第三种形式:应用拦截器

<? xml version="1.0" encoding="UTF-8" ?>  < beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:aop ="http://www.springframework.org/schema/aop"      xsi:schemaLocation ="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> < bean id ="sessionFactory"class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >  
        < property name ="configLocation" value ="classpath:hibernate.cfg.xml"   />  
        < property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration"   /> </ bean >  

    <!-- 定义事务管理器(申明式的事务)-->  
    < bean id ="transactionManager" class ="org.springframework.orm.hibernate3.HibernateTransactionManager" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean >  

    < bean id ="transactionInterceptor"  
        class ="org.springframework.transaction.interceptor.TransactionInterceptor" >  
        < property name ="transactionManager" ref ="transactionManager"   />  
        <!-- 配置事务属性 -->  
        < property name ="transactionAttributes" >  
            < props >  
                < prop key ="*" > PROPAGATION_REQUIRED </ prop >  
            </ props >  
        </ property >  
    </ bean > < bean class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >  
        < property name ="beanNames" >  
            < list >  
                < value > *Dao </ value >              </ list >  
        </ property >  
        < property name ="interceptorNames" >  
            < list >  
                < value > transactionInterceptor </ value >  
            </ list >  
        </ property >  
    </ bean >  

    <!-- 配置 DAO --> < bean id ="userDao" class ="com.bluesky.spring.dao.UserDaoImpl" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean >  </ beans >

第四种形式:应用 tx 标签配置的拦截器

<? xml version="1.0" encoding="UTF-8" ?>  < beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:aop ="http://www.springframework.org/schema/aop" xmlns:tx ="http://www.springframework.org/schema/tx" xsi:schemaLocation ="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> < context:annotation-config /> < context:component-scan base-package ="com.bluesky"/> < bean id ="sessionFactory"class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >  
        < property name ="configLocation" value ="classpath:hibernate.cfg.xml"   />  
        < property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration"   /> </ bean >  

    <!-- 定义事务管理器(申明式的事务)-->  
    < bean id ="transactionManager" class ="org.springframework.orm.hibernate3.HibernateTransactionManager" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean > < tx:advice id ="txAdvice" transaction-manager ="transactionManager" > < tx:attributes > < tx:method name ="*" propagation ="REQUIRED"   /> </ tx:attributes > </ tx:advice > < aop:config > < aop:pointcut id ="interceptorPointCuts" expression ="execution(* com.bluesky.spring.dao.*.*(..))"   /> < aop:advisor advice-ref ="txAdvice" pointcut-ref ="interceptorPointCuts"   />        
    </ aop:config >  </ beans >

第五种形式:全注解

<? xml version="1.0" encoding="UTF-8" ?>  < beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:aop ="http://www.springframework.org/schema/aop" xmlns:tx ="http://www.springframework.org/schema/tx" xsi:schemaLocation ="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> < context:annotation-config /> < context:component-scan base-package ="com.bluesky"/> < tx:annotation-driven transaction-manager ="transactionManager"/> < bean id ="sessionFactory"class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >  
        < property name ="configLocation" value ="classpath:hibernate.cfg.xml"   />  
        < property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration"   /> </ bean >  

    <!-- 定义事务管理器(申明式的事务)-->  
    < bean id ="transactionManager" class ="org.springframework.orm.hibernate3.HibernateTransactionManager" > < property name ="sessionFactory" ref ="sessionFactory"   /> </ bean >  </ beans >

此时在 DAO 上需加上 @Transactional 注解,如下:

package com.bluesky.spring.dao; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.stereotype.Component; import com.bluesky.spring.domain.User;

@Transactional
@Component("userDao") public   class UserDaoImpl extends HibernateDaoSupport implements UserDao {public List < User > listUsers() {return   this .getSession().createQuery("from User").list();}

    ![image](https://upload-images.jianshu.io/upload_images/25149744-64eb3e46bfeeae4e.gif?imageMogr2/auto-orient/strip)

}

spring外面事务的流传属性和 事务隔离级别

一、Propagation(事务的流传属性)

Propagation:key 属性确定代理应该给哪个办法减少事务行为。这样的属性最重要的部份是流传行为。有以下选项可供使用:

PROPAGATION_REQUIRED– 反对以后事务,如果以后没有事务,就新建一个事务。这是最常见的抉择。

PROPAGATION_SUPPORTS– 反对以后事务,如果以后没有事务,就以非事务形式执行。

PROPAGATION_MANDATORY– 反对以后事务,如果以后没有事务,就抛出异样。

PROPAGATION_REQUIRES_NEW– 新建事务,如果以后存在事务,把以后事务挂起。

PROPAGATION_NOT_SUPPORTED– 以非事务形式执行操作,如果以后存在事务,就把以后事务挂起。

PROPAGATION_NEVER– 以非事务形式执行,如果以后存在事务,则抛出异样。

1:PROPAGATION_REQUIRED

退出以后正要执行的事务不在另外一个事务里,那么就起一个新的事务

比如说,ServiceB.methodB 的事务级别定义为 PROPAGATION_REQUIRED, 那么因为执行 ServiceA.methodA 的时候,

ServiceA.methodA 曾经起了事务,这时调用 ServiceB.methodB,ServiceB.methodB 看到本人曾经运行在 ServiceA.methodA

的事务外部,就不再起新的事务。而如果 ServiceA.methodA 运行的时候发现自己没有在事务中,他就会为本人调配一个事务。

这样,在 ServiceA.methodA 或者在 ServiceB.methodB 内的任何中央出现异常,事务都会被回滚。即便 ServiceB.methodB 的事务曾经被

提交,然而 ServiceA.methodA 在接下来 fail 要回滚,ServiceB.methodB 也要回滚

2:PROPAGATION_SUPPORTS

如果以后在事务中,即以事务的模式运行,如果以后不再一个事务中,那么就以非事务的模式运行

3:PROPAGATION_MANDATORY

必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异样

4:PROPAGATION_REQUIRES_NEW

这个就比拟绕口了。比方咱们设计 ServiceA.methodA 的事务级别为 PROPAGATION_REQUIRED,ServiceB.methodB 的事务级别为 PROPAGATION_REQUIRES_NEW,

那么当执行到 ServiceB.methodB 的时候,ServiceA.methodA 所在的事务就会挂起,ServiceB.methodB 会起一个新的事务,期待 ServiceB.methodB 的事务实现当前,

他才继续执行。他与 PROPAGATION_REQUIRED 的事务区别在于事务的回滚水平了。因为 ServiceB.methodB 是新起一个事务,那么就是存在

两个不同的事务。如果 ServiceB.methodB 曾经提交,那么 ServiceA.methodA 失败回滚,ServiceB.methodB 是不会回滚的。如果 ServiceB.methodB 失败回滚,

如果他抛出的异样被 ServiceA.methodA 捕捉,ServiceA.methodA 事务依然可能提交。

5:PROPAGATION_NOT_SUPPORTED

以后不反对事务。比方 ServiceA.methodA 的事务级别是 PROPAGATION_REQUIRED,而 ServiceB.methodB 的事务级别是 PROPAGATION_NOT_SUPPORTED,

那么当执行到 ServiceB.methodB 时,ServiceA.methodA 的事务挂起,而他以非事务的状态运行完,再持续 ServiceA.methodA 的事务。

6:PROPAGATION_NEVER

不能在事务中运行。假如 ServiceA.methodA 的事务级别是 PROPAGATION_REQUIRED,而 ServiceB.methodB 的事务级别是 PROPAGATION_NEVER,

那么 ServiceB.methodB 就要抛出异样了。

7:PROPAGATION_NESTED

了解 Nested 的要害是 savepoint。他与 PROPAGATION_REQUIRES_NEW 的区别是,PROPAGATION_REQUIRES_NEW 另起一个事务,将会与他的父事务互相独立,

而 Nested 的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最初回滚,他也要回滚的。

而 Nested 事务的益处是他有一个 savepoint。


ServiceA {
/**

  • 事务属性配置为 PROPAGATION_REQUIRED

*/
void methodA() {
try {
//savepoint
ServiceB.methodB(); //PROPAGATION_NESTED 级别
} catch (SomeException) {
// 执行其余业务, 如 ServiceC.methodC();
}
}
}


也就是说 ServiceB.methodB 失败回滚,那么 ServiceA.methodA 也会回滚到 savepoint 点上,ServiceA.methodA 能够抉择另外一个分支,比方

ServiceC.methodC,继续执行,来尝试实现本人的事务。

然而这个事务并没有在 EJB 规范中定义。

二、Isolation Level(事务隔离等级):

1、Serializable:最严格的级别,事务串行执行,资源耗费最大;

2、REPEATABLE READ:保障了一个事务不会批改曾经由另一个事务读取但未提交(回滚)的数据。防止了“脏读取”和“不可反复读取”的状况,然而带来了更多的性能损失。

3、READ COMMITTED: 大多数支流数据库的默认事务等级,保障了一个事务不会读到另一个并行事务已批改但未提交的数据,防止了“脏读取”。该级别实用于大多数零碎。

4、Read Uncommitted:保障了读取过程中不会读取到非法数据。隔离级别在于解决多事务的并发问题。

咱们晓得并行能够进步数据库的吞吐量和效率,然而并不是所有的并发事务都能够并发运行,这须要查看数据库教材的可串行化条件判断了。

这里就不论述。

咱们首先说并发中可能产生的 3 中不讨人喜欢的事件

1:Dirty reads– 读脏数据。也就是说,比方事务 A 的未提交(还仍然缓存)的数据被事务 B 读走,如果事务 A 失败回滚,会导致事务 B 所读取的的数据是谬误的。

2:non-repeatable reads– 数据不可反复读。比方事务 A 中两处读取数据 -total- 的值。在第一读的时候,total 是 100,而后事务 B 就把 total 的数据改成 200,事务 A 再读一次,后果就发现,total 居然就变成 200 了,造成事务 A 数据凌乱。

3:phantom reads– 幻象读数据,这个和 non-repeatable reads 类似,也是同一个事务中屡次读不统一的问题。然而 non-repeatable reads 的不统一是因为他所要取的数据集被扭转了(比方 total 的数据),然而 phantom reads 所要读的数据的不统一却不是他所要读的数据集扭转,而是他的条件数据集扭转。比方 Select account.id where account.name=”ppgogo*”, 第一次读去了 6 个符合条件的 id,第二次读取的时候,因为事务 b 把一个帐号的名字由 ”dd” 改成 ”ppgogo1″,后果取出来了 7 个数据。

|   | Dirty reads | non-repeatable reads | phantom reads |
| Serializable | 不会 | 不会 | 不会 |
| REPEATABLE READ | 不会 | 不会 | 会 |
| READ COMMITTED | 不会 | 会 | 会 |
| Read Uncommitted | 会 | 会 | 会 |

三、readOnly

事务属性中的 readOnly 标记示意对应的事务应该被最优化为只读事务。

这是一个最优化提醒。在一些状况下,一些事务策略可能起到显著的最优化成果,例如在应用 Object/Relational 映射工具(如:Hibernate 或 TopLink)时防止 dirty checking(试图“刷新”)。

四、Timeout

在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在 JTA 中,这将被简略地传递到 J2EE 服务器的事务协调程序,并据此失去相应的解释


spring外面事务的流传属性和 事务隔离级别

一、Propagation(事务的流传属性)

Propagation:key 属性确定代理应该给哪个办法减少事务行为。这样的属性最重要的部份是流传行为。有以下选项可供使用:PROPAGATION_REQUIRED– 反对以后事务,如果以后没有事务,就新建一个事务。这是最常见的抉择。

PROPAGATION_SUPPORTS– 反对以后事务,如果以后没有事务,就以非事务形式执行。

PROPAGATION_MANDATORY– 反对以后事务,如果以后没有事务,就抛出异样。

PROPAGATION_REQUIRES_NEW– 新建事务,如果以后存在事务,把以后事务挂起。

PROPAGATION_NOT_SUPPORTED– 以非事务形式执行操作,如果以后存在事务,就把以后事务挂起。

PROPAGATION_NEVER– 以非事务形式执行,如果以后存在事务,则抛出异样。

1:PROPAGATION_REQUIRED

退出以后正要执行的事务不在另外一个事务里,那么就起一个新的事务

比如说,ServiceB.methodB 的事务级别定义为 PROPAGATION_REQUIRED, 那么因为执行 ServiceA.methodA 的时候,

ServiceA.methodA 曾经起了事务,这时调用 ServiceB.methodB,ServiceB.methodB 看到本人曾经运行在 ServiceA.methodA

的事务外部,就不再起新的事务。而如果 ServiceA.methodA 运行的时候发现自己没有在事务中,他就会为本人调配一个事务。

这样,在 ServiceA.methodA 或者在 ServiceB.methodB 内的任何中央出现异常,事务都会被回滚。即便 ServiceB.methodB 的事务曾经被

提交,然而 ServiceA.methodA 在接下来 fail 要回滚,ServiceB.methodB 也要回滚

2:PROPAGATION_SUPPORTS

如果以后在事务中,即以事务的模式运行,如果以后不再一个事务中,那么就以非事务的模式运行

3:PROPAGATION_MANDATORY

必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异样

4:PROPAGATION_REQUIRES_NEW

这个就比拟绕口了。比方咱们设计 ServiceA.methodA 的事务级别为 PROPAGATION_REQUIRED,ServiceB.methodB 的事务级别为 PROPAGATION_REQUIRES_NEW,

那么当执行到 ServiceB.methodB 的时候,ServiceA.methodA 所在的事务就会挂起,ServiceB.methodB 会起一个新的事务,期待 ServiceB.methodB 的事务实现当前,

他才继续执行。他与 PROPAGATION_REQUIRED 的事务区别在于事务的回滚水平了。因为 ServiceB.methodB 是新起一个事务,那么就是存在

两个不同的事务。如果 ServiceB.methodB 曾经提交,那么 ServiceA.methodA 失败回滚,ServiceB.methodB 是不会回滚的。如果 ServiceB.methodB 失败回滚,

如果他抛出的异样被 ServiceA.methodA 捕捉,ServiceA.methodA 事务依然可能提交。

5:PROPAGATION_NOT_SUPPORTED

以后不反对事务。比方 ServiceA.methodA 的事务级别是 PROPAGATION_REQUIRED,而 ServiceB.methodB 的事务级别是 PROPAGATION_NOT_SUPPORTED,

那么当执行到 ServiceB.methodB 时,ServiceA.methodA 的事务挂起,而他以非事务的状态运行完,再持续 ServiceA.methodA 的事务。

6:PROPAGATION_NEVER

不能在事务中运行。假如 ServiceA.methodA 的事务级别是 PROPAGATION_REQUIRED,而 ServiceB.methodB 的事务级别是 PROPAGATION_NEVER,

那么 ServiceB.methodB 就要抛出异样了。

7:PROPAGATION_NESTED

了解 Nested 的要害是 savepoint。他与 PROPAGATION_REQUIRES_NEW 的区别是,PROPAGATION_REQUIRES_NEW 另起一个事务,将会与他的父事务互相独立,

而 Nested 的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最初回滚,他也要回滚的。

而 Nested 事务的益处是他有一个 savepoint。


ServiceA {
/**

  • 事务属性配置为 PROPAGATION_REQUIRED

*/
void methodA() {
try {
//savepoint
ServiceB.methodB(); //PROPAGATION_NESTED 级别
} catch (SomeException) {
// 执行其余业务, 如 ServiceC.methodC();
}
}
}


也就是说 ServiceB.methodB 失败回滚,那么 ServiceA.methodA 也会回滚到 savepoint 点上,ServiceA.methodA 能够抉择另外一个分支,比方

ServiceC.methodC,继续执行,来尝试实现本人的事务。

然而这个事务并没有在 EJB 规范中定义。

二、Isolation Level(事务隔离等级):

1、Serializable:最严格的级别,事务串行执行,资源耗费最大;

2、REPEATABLE READ:保障了一个事务不会批改曾经由另一个事务读取但未提交(回滚)的数据。防止了“脏读取”和“不可反复读取”的状况,然而带来了更多的性能损失。

3、READ COMMITTED: 大多数支流数据库的默认事务等级,保障了一个事务不会读到另一个并行事务已批改但未提交的数据,防止了“脏读取”。该级别实用于大多数零碎。

4、Read Uncommitted:保障了读取过程中不会读取到非法数据。隔离级别在于解决多事务的并发问题。

咱们晓得并行能够进步数据库的吞吐量和效率,然而并不是所有的并发事务都能够并发运行,这须要查看数据库教材的可串行化条件判断了。

这里就不论述。

咱们首先说并发中可能产生的 3 中不讨人喜欢的事件

1:Dirty reads– 读脏数据。也就是说,比方事务 A 的未提交(还仍然缓存)的数据被事务 B 读走,如果事务 A 失败回滚,会导致事务 B 所读取的的数据是谬误的。

2:non-repeatable reads– 数据不可反复读。比方事务 A 中两处读取数据 -total- 的值。在第一读的时候,total 是 100,而后事务 B 就把 total 的数据改成 200,事务 A 再读一次,后果就发现,total 居然就变成 200 了,造成事务 A 数据凌乱。

3:phantom reads– 幻象读数据,这个和 non-repeatable reads 类似,也是同一个事务中屡次读不统一的问题。然而 non-repeatable reads 的不统一是因为他所要取的数据集被扭转了(比方 total 的数据),然而 phantom reads 所要读的数据的不统一却不是他所要读的数据集扭转,而是他的条件数据集扭转。比方 Select account.id where account.name=”ppgogo*”, 第一次读去了 6 个符合条件的 id,第二次读取的时候,因为事务 b 把一个帐号的名字由 ”dd” 改成 ”ppgogo1″,后果取出来了 7 个数据。

 Dirty reads    non-repeatable reads    phantom reads

Serializable 不会 不会 不会
REPEATABLE READ 不会 不会 会
READ COMMITTED 不会 会 会
Read Uncommitted 会 会 会

三、readOnly

事务属性中的 readOnly 标记示意对应的事务应该被最优化为只读事务。

这是一个最优化提醒。在一些状况下,一些事务策略可能起到显著的最优化成果,例如在应用 Object/Relational 映射工具(如:Hibernate 或 TopLink)时防止 dirty checking(试图“刷新”)。

四、Timeout

在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在 JTA 中,这将被简略地传递到 J2EE 服务器的事务协调程序,并据此失去相应的解释

20110112

数据库提供了四种事务隔离级别, 不同的隔离级别采纳不同的锁类开来实现.

在四种隔离级别中, Serializable 的级别最高, Read Uncommited 级别最低.

大多数数据库的默认隔离级别为: Read Commited, 如 Sql Server , Oracle.

多数数据库默认的隔离级别为 Repeatable Read, 如 MySQL InnoDB 存储引擎

即便是最低的级别, 也不会呈现 第一类 失落 更新问题 . 

1. 脏读(事务没提交,提前读取):脏读就是指当一个事务正在拜访数据,并且对数据进行了批改,而这种批改还没有提交到数据库中,这时,另外一个事务也拜访这个数据,而后应用了这个数据。

2. 不可反复读 (两次读的不统一):是指在一个事务内,屡次读同一数据。在这个事务还没有完结时,另外一个事务也拜访该同一数据。那么,在第一个事务中的两次读数据之间,因为第二个事务的批改,那么第一个事务两次读到的的数据可能是不一样的。这样就产生了在一个事务内两次读到的数据是不一样的,因而称为是不可反复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可反复。如果只有在作者全副实现编写后编辑人员才能够读取文档,则能够防止该问题。
3. 幻读 : 是指当事务不是独立执行时产生的一种景象,例如第一个事务对一个表中的数据进行了批改,这种批改波及到表中的全副数据行。同时,第二个事务也批改这个表中的数据,这种批改是向表中插入一行新数据。那么,当前就会产生操作第一个事务的用户发现表中还有没有批改的数据行,就好象产生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新资料增加到该文档中。如果在编辑人员和生产部门实现对原始文档的解决之前,任何人都不能将新资料增加到文档中,则能够防止该问题。
4. 第一类更新失落(回滚失落)
  当 2 个事务更新雷同的数据源,如果第一个事务被提交,而另外一个事务却被撤销,那么会连同第一个事务所做的跟新也被撤销。也就是说第一个事务做的跟新失落了。
5. 第二类更新失落(笼罩失落)
  第二类更新失落切实理论利用中常常遇到的并发问题,他和不可反复读实质上是同一类并发问题,通常他被看做不可反复读的特例:当 2 个或这个多个事务查问同样的记录而后各自基于最后的查问后果更新该行时,会造成第二类失落更新。因为每个事务都不晓得不晓得其余事务的存在,最初一个事务对记录做的批改将笼罩其余事务对该记录做的已提交的跟新 …
补充 : 基于元数据的 Spring 申明性事务 :

Isolation 属性一共反对五种事务设置,具体介绍如下:

l          DEFAULT 应用数据库设置的隔离级别 (默认),由 DBA 默认的设置来决定隔离级别 .

l          READ_UNCOMMITTED 会呈现脏读、不可反复读、幻读 (隔离级别最低,并发性能高)

l          READ_COMMITTED  会呈现不可反复读、幻读问题(锁定正在读取的行)

l          REPEATABLE_READ 会出幻读(锁定所读取的所有行)

l          SERIALIZABLE 保障所有的状况不会产生(锁表)

不可反复读的重点是批改 :
同样的条件 ,   你读取过的数据 ,   再次读取进去发现值不一样了
幻读的重点在于新增或者删除
同样的条件 ,   第 1 次和第 2 次读出来的记录数不一样!

转载:https://blog.csdn.net/it_man/article/details/5074371

退出移动版