数据库事务有严格的定义,它必须满足4个特性:
原子性(Atomic):表示组成一个事务的多个数据库操作是一个不可分割的原子单元只有所有的操作执行成功,整个事务才能提交,事务中任何一个数据库操作失败,己经执行的任何操作都必须撤销,让数据主加返回到初状态。
一致性(Consistency):事务操作成功后,数据所处的状态和它的业务规则是一致的,即数据不会被被破坏。如从A账户转账100元到B账户,不管操作成功与否,A和B的存款总额不变的。
隔离性(Isolation):在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰。准确地说,并非要求做到完全无干扰,数据库规定了多种事务隔离级别,不同隔离级别,对应不同的干扰程度,隔离级别越高,数据一致性越好,但并发性越弱。
持久性(Durabiliy):一旦事务提交成功后,事务中所有的数据操作都必须被持久化到数据库中,取出使提交事务后,数据库马上崩溃,在数据库重启时,也必须保证能够通过某种机制恢复数据。
在这些事务特性中,数据“一致性”是最终目标,其他特性都是为达到这个目标的措施、要求或手段。
数据并发的问题:
脏读:A事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。如果恰巧B事务回滚,那么A事务读到的数据根本是不被承认的。
不可重复读:A事务读取到了B事务已经提交的更改的数据。假设A在取款事务的过程中,B往该账户转账100元,A两次读取的账户的余额发生不一致。
幻象读:A事务读取了B事务提交的新增数据,这时A事将出现幻象读。幻象读一般发生在计算数据的事务中,举一个例子,假设银行系统在同一个事务中,两次统计存款账户的总金额,在两次统计过程中刚好新增了一个存款户,并存入100元,这时两次统计的总金额不一致。
幻读和不可重复读是两个容易混淆的概念,前者是指读到了其他己经提交的事务的新数据,而后者是指读到了己经提交事务的更改数据(更改或删除),为了避免这种情况,采取的对策是不同的,防止读取到更改数据,只需要对操作的数据添加行级锁,阻止操作中的数据发生
变化,而防止读取到新增数据,则往往需要对操作的灵气添加表级锁--将对整个表锁定,防止新增数据。
第一类丢失更新:A事务撤销时,把己提交的B事务的更新数据覆盖了。
第二类丢失更新:A事务覆盖B事务己经提交的数据,造成B事务所做的操作丢失。
行共享锁定:一般通过select for update 语句隐式获得共享锁定,在Oracle中用户也可以通过LOCK TABLE IN ROW SHARE MODE语句显式获得行共享锁定。行共享锁定并不防止对数据行进行更改的操作,但是可以防止其他会话获取独占性数据表锁定,允许进行多个并发的行共
享和行独占性锁定,还允许进行数据表的共享或者采用共享行独占锁定。
行独占锁定:通过一条INSERT、UPDATE 或DELETE 语句隐式获取,或者通过一条LOCK TABLE IN ROW EXCLUSIVE MODE 语句显式获取。这个锁定可以防止其他会话获取一个共享锁定、共享行独占锁定或独占锁定。
表共享锁定:通过LOCK TABLE IN SHARE MODE语句显式获得。这种锁定可以防止其他会话获得行独占锁定(INSERT、UPDATE 或DELETE),或者防止其他表共享行独占锁定或表独占锁定,它允许在表中拥多个共享和表共享锁定。该锁定可以让会话具有对表事务级一致访问,因为
其他会话在用户提交或者回滚该 事务并释放对该表锁定之前不能更改这个被锁定的表。
表共享行独占:通过LOCK TABLE IN SHARE ROW EXCLUSIVE MODE 语句显式获得。这种锁定可防止其他会获得一个表共享、行独占或者表独占锁颇定,它允许其他行共享锁定。这种锁定类似于表共享锁定,只是一次只能对一个表放置一个表共享行独占锁定。如果A会话拥有该锁定
,则B会话可执行SELECT ROR UPDATE操作,但是如果B会话试图更新选择行,则需要等待。
表独占:通过LOCK TABLE IN EXCLUSIVE MODE 显式获得。这个锁定防止其他会话对该表的任何其他锁定。
隔离级别 脏读 不可重复读 幻读 第一类丢失更新 第二类丢失更新
-----------------------------------------------------------------------------------------
read uncommited yes yes yes no yes
read committed no yes yes no yes
repeatable read no no yes no no
serializable no no no no no
-----------------------------------------------------------------------------------------
Spring 的事务管理器实现类
事务 说明
org.springframework.orm.jpa.JpaTransactionManager 使用JPA进行持久化时,使用该事务管理器
org.springframework.orm.hibernate3.HibernateTransactionManager 使用Hibernate3.0
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用JDBC 或iBatis
org.springframework.orm.jdo.JdoTransactionManager 使用JDO
org.springframework.transaction.jta.JtaTransactionManager 具有多个数据源的全局事务使用事务管理器
----------------------------------------------------------------------------------------
事务的传播行为类型 说明
--------------------------------------------------------------------------------------
propagation_required 如果当前没有事务,就新建一个事务,如果己经存在一个事务中,加入到这个事务中。这是最常见的选择。
propagation_supports 支持当前事务,如果当前没有事务,就以非事务方式执行。
propagation_mandatory 使用当前事务,如果当前没有事务,就抛出异常。
propagation_requires_new 新建事务,如果当前存在事务,把当前事务挂起。
propagation_not_suppoprted 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
propagation_never 以非事务方式执行,如查当前存在事务,则抛出异常。
propatation_nested 如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则执行与propagation_required
-----------------------------------------------------------------------------------------
编程式的事务管理
Spring为编程式事务客理提供了模板类org.springframework.transaction.support.TransactionTemplate
使用xml配置声明式事务
Spring的声明事务管理是通过SpringAOP实现的。
Spring默认的事务回滚规则为:运行期异常回滚,检查型异常不回滚。
----------------------------------------------------------------------------------------------
我们可以得出这样的结论:
在相同的线程中进行相互嵌套调用的事务方法工作于相同的事务中。如果这些相互嵌套调用的方法工用在不同的线程中,则不同线程下的事务方法工作在独立的事务中。
--------------------------------------------------------------------------
事务隔离级别对并发问题解决情况
序号 混合数据库访问技术框架 事务管理器
1 Hibernate+Spring JDBC或iBatis org.springframework.orm.hibernate3.HibernateTransactionManager
2 JPA+Spring JDBC或iBatis org.springframework.orm.jpa.JpaTransactionManger
3 JDO+Spring JDBC或iBatis org.springframework.orm.jdo.JdoTransactionManger
------------------------------------------------------------------------------------------------------
不能被Spring AOP事务增强的方法
序号 动态代理策略 不能被事务增强的方法
1 基于接口的动态代理 除public 外的其他所有的方法,此外public static也不能被增强
2 基于CGLib动态代理 private、static、final的方法
---------------------------------------------------------
spring整合其他ORM框架
1.在spring中配置Hibernate文件:
<bean id="sessionFactory" class="org.springframework.orm.hibernatge3.LocalSessionFactoryBean"
p:configLocation="classpath:hibernate.cfg.xml"/>