Spring事务隔离级别和传播行为

先说下数据读取的几个异常情况:

1.读取脏数据(Dirty reads)。就是读取到了其他事务没有提交的数据。比如2个并发的事务A,B。A修改了字段age(原来为18)的值为20,这时B读取到age的值为20。如果A事务在后面的操作中回滚了,这样事务B取的age=20就是个脏数据。这种情况发生的很少,因为主流的数据库的隔离级别都能保证避免脏数据的读取。

2.不可重复读(non-repeatable reads)。就是修改了其他事务已经读取的数据。比如2个并发的事务A,B。A读到字段age=18。这时B对改字段做了修改age=20。这样事务A如果再次读取age时就会发现两次得到的数据是不同的。

3.幻读(phantom reads)。它和不可重复读类似,但也不同,它不是修改其他事务已经读取的数据,而是新增了其他进程没有读到的数据。这样会造成这种情况:A读取user_info表的记录数是100,事务B新增了2条记录,这样A再次读取时就会发现记录数成了102,数据不一致了。

而事务的隔离级别就是为了防止以上数据不一致的情况发生。

                          Dirty reads          non-repeatable reads            phantom reads

Serializable不会不会不会

REPEATABLEREAD不会不会会

READCOMMITTED不会会会

Read Uncommitted         会                       会                              会

实现原理就是对数据库表进行加锁。

Read Uncommitted自然是不加锁,READ COMMITTED是读取时对读取的行加锁,读取完成之后就解锁。REPEATABLE READ也是读取的内容加锁,但解锁是要等到所在事务提交。Read Uncommitted就是全表加锁。

Serializable的隔离级别效率太差,hibernate默认的隔离级别是REPEATABLE READ,不保证避免幻读。

配置的话具体见spring手册,下面从网络上考的一段配置文件:

<bean id="transactionManager"
  class="org.springframework.transaction.jta.JtaTransactionManager">
    <constructor-arg>
        <ref local="jtaTransactionManager" />
    </constructor-arg>
</bean>

<bean id="orderService" 
  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
        <ref local="transactionManager" />
    </property>
    <property name="proxyInterfaces">
        <list>
            <value>sample.services.OrderService</value>
        </list>
    </property>
    <property name="target">
        <ref local="orderServiceTarget" />
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="save*">PROPAGATION_REQUIRED, ISOLATION_SERIALIZABLE</prop>
            <prop key="delete*">PROPAGATION_REQUIRED, ISOLATION_READ_UNCOMMITTED</prop>
            <prop key="find*">PROPAGATION_REQUIRED, ISOLATION_READ_UNCOMMITTED, 
            readOnly</prop>
        </props>
    </property>
</bean>
 

相关推荐