事务的基本概念

定义事务的属性

在spring中,声明式事务是通过事务属性来定义的.事务属性描述了事务策略如何应用到方法上.事务属性包含了5个方面,如下图所示:

事物的属性

事务的传播行为(Propagation)

传播行为定义了客户端与被调用方法之间的事务边界,她简单的回答了这样一个问题,即新的事务应该被启动还是被挂起,或者方法是否要在事务环境下运行.

spring定义了以下传播规则供选择,在org.springframework.transaction.TransactionDefinition中:

事物的传递情况

隔离级别(Isolation)

隔离级别定义了一个事务可能受到其他并发事务的影响程度.也就是事务对事务性数据的自私程度.

  1. 脏读(Dirty reads):发生在一个事务读取了另一个事务改写但尚未提交的数据时.如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的.
  2. 不可重复读(Nonrepeatable read):发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时.通常是因为另一个并发事务在两次查询期间更新了数据.
  3. 幻读(Phantom read):她与不可重复读类似.发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时.在随后的查询中,第一个事务就会发现多了一些原本不存在的记录.

在理想的情况下,事务之间是完全隔离的,从而可以防止这些问题的发生.但是完全隔离会导致性能问题.因为他通常涉及锁定数据库中的记录.侵占性的锁定会阻碍并发性,要求事务互相等待以完成各自的工作.考虑到这些问题,spring定义了以下隔离级别,在org.springframework.transaction.TransactionDefinition中:

事物的隔离级别

并不是所有的数据源都支持表中的隔离级别,需要查阅你的资源管理器文档来确定哪些隔离级别是可用的.

只读(Read-Only)

声明式事务的第三个特性是他是否为只读事务.如果事务只对后端的数据进行读操作,数据可以利用事务的只读特性来进行一些特定的优化.通过将事务设置为只读,你就可以给数据库一个机会,让他应用他认为合适的优化措施.

因为只读优化是在事务启动的时候由数据库实施的,只有对那些具备启动一个新的事务的传播行为(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED)的方法来说,将事务声明为只读才有意义.

另外,如果采用Hibernate作为持久化机制,那么将事务声明为只读会导致Hibernate的flush模式被设置为FLUSH_NEVER.这会告诉Hibernate避免和数据库进行不必要的对象同步,并将所有的更新延迟到事务结束.

事务超时(TimeOut)

为了使应用程序很好的运行,事务不能运行太长的时间.假设事务的运行时间变得特别长,因为事务可能涉及对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源.你可以声明一个事务,在特定的秒数后自动回滚,而不是等待其结束.

因为超时时钟会在事务开始时启动,所以只有对那些具备启动一个新的事务的传播行为(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED)的方法来说,将事务声明超时才有意义.

回滚规则(Rollback Rules)

这些规则定义了哪些异常会导致事务回滚而哪些不会.默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚.但是你可以声明事务在遇到特定的检查异常时像遇到运行期异常那样回滚.同样,你可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常.