由数据库的隔离级别到spring对数据库的事物控制

原创
2016/03/23 15:31
阅读数 144

一、关于事务的隔离级别:
sql定义四种隔离级别(由低到高)
1 Read Uncommitted 读取未提交内容
2 Read Committed 读取提交内容
3 Repeatable Read 可重读
4 Serializable 可串行化
二、不同隔离级别所面对的问题
四种隔离级别通过不同的锁类型实现,在读取同一个数据,就容易发生问题。
问题有三种:脏读,不可重复读,幻读。
不同的隔离级别可能产生的问题也不同
隔离级别     脏读   不可重复读   幻读
Read Uncommitted  √       √        √
Read Committed      ×       √        √
Repeatable Read      ×       ×        √
Serializable               ×       ×        ×
三、产生问题的原因
脏读:首先有行记录a,事务A将记录a修改为a1,但尚未提交(可能会提交失败)。事务B读取到了未提交的数据a1。
原因:因为一旦事务A回滚,那么事务B读取到的a1就是无效数据。

不可重复读:同一事务对一条记录读取2次,得到的结果不一致。
原因:两次读取的过程中,事务B对这条记录进行了修改。

幻读:事务A 读取一条where子句的结果集,2次读取得到的记录多出n条。
原因:两次读取过程中,事务B对数据库插入新行,并且满足事物A的where 条件。

oracle数据库 只支持Read Committed 和 Serializable,默认第二种;
mysql 支持四种,mysql默认事务级别是第三种,innoDB版本并发控制解决了幻读问题(

有待研究http://www.bitscn.com/pdb/mysql/201405/227973.html)。
 
session是程序与数据库的一次连接,事务是session对数据库的一次操作(个人理解)

hibernate 一级缓存(session级别),二级缓存(SessionFactory级别)?
http://blog.csdn.net/defonds/article/details/2308972

四、事务的传播

1、PROPAGATION_REQUIRED
如果当前没有事务,则新建一个事务,如果已经存在一个事务中,加入到这个事务中,这是最常见的选择。
2、PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行
3、PROPAGATION_MANDATORY
使用当前的事务,如果当前没事务,就抛出异常
4、PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,就把当前事务挂起
5、PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
6、PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常
7、PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事物,则执行与PROPAGATION_REQUIRED类似的操作。

五、spring对数据源及事务的管理?


http://www.360doc.com/content/14/0730/15/1073512_398133924.shtml



5.1、spring数据源的配置:对jdbc ,hibernate,jta (mybatis是基于jdbc)
参考(http://thaim.iteye.com/blog/1753801)
=====================jdbc DataSource=========================
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

The related PlatformTransactionManager bean definition will then have a reference to the DataSource definition. It will look like this:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

======================JTA=====================================
If you use JTA in a Java EE container then you use a container DataSource, obtained through JNDI, in conjunction with Spring’s JtaTransactionManager.
This is what the JTA and JNDI lookup version would look like:

<?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:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee.xsd">

    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>

    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

    <!-- other <bean/> definitions here -->

</beans>

The JtaTransactionManager does not need to know about the DataSource, or any other specific resources,
because it uses the container’s global transaction management infrastructure.

=========================hibernate===========================
the DataSource bean definition will be similar to the local JDBC example shown previously and thus is not shown in the following example.
The txManager bean in this case is of the HibernateTransactionManager type. In the same way as the DataSourceTransactionManager needs a reference to the DataSource, the HibernateTransactionManager needs a reference to the SessionFactory.
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingResources">
        <list>
            <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
        </value>
    </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
==========================hibenate jta配置===============================
If you are using Hibernate and Java EE container-managed JTA transactions, then you should simply use the same JtaTransactionManager as in the previous JTA example for JDBC.
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
=============================================================

5.2全局事务(分布式事务)和局部事务(本地事务)区别

局部事务:针对单一数据源;本地事务不涉及多个数据来源。
全局事务:多数据源,及数据源在分布式环境中;资源管理器管理和协调的事务,可以跨越多个数据库和进程。

参考(http://blog.csdn.net/sunitjy/article/details/6585301)
spring+mybatis+atomikos 实现JTA事务

参考 http://www.programgo.com/article/66523335035/

展开阅读全文
打赏
1
7 收藏
分享
加载中
更多评论
打赏
0 评论
7 收藏
1
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部