标签:
事务就是一组数据库操作,但这组操作是具有原子性的(atomic)。所谓原子操作,即这组数据库操作要么就都执行成功,要么就一个也没执行。当有一些操作成功了(“成功”指数据库里的数据已更新或提交),但中间出现异常,后边的也就无法执行时,事务要回滚,即恢复到什么也没执行以前的状态。
举个比较常见的例子,一位顾客要进行银行转帐,把100元从A帐户转到B帐户,一般的过程是把A帐户的总额减去100,B帐户的总额加上100(只考虑最简单情况)。当在A帐户总额减去100后出现异常情况,使得无法再对B帐户进行操作。如果没使用事务,那么这位顾客就损失了100元,但如果使用了事务,那么出现异常后,事务回滚,使得A帐户总额恢复到减去100以前的金额。虽然使用事务并没有达到顾客转帐的目的,但避免了出现异常情况时顾客的损失。
事务就相当于我们做一件事情(这件事由许多小的步骤组成),要么我们就把这件事情完完整整地做成功,要么我们就一点也不要做。不能做到半截撂摊子不干了。 |
回到Spring来,Spring的Dao框架对事务提供了强大的支持。它包括有两种事物管理,即:
编程式事物管理(programmatic tansaction management)
声明式事物管理(Declarative tansaction management)
所谓编程式事物管理,就是把事物管理以代码的形式编写到你的应用中要使用事物管理的地方,灵活性较强。而声明式事物管理是以配置文件的形式在xml文件中定义,好处是不具有代码入侵性,当不需要事物管理时,可以直接修改配置文件,而不用修改代码。以后会介绍这两种事物管理。
在Spring中,主要涉及以下几种事物属性:
1. 传播行为(propagation behavior)
它是对事物的起始,暂停,终止时刻的定义,主要有以下几种
参数 | 含义 |
PROPAGATION_REQUIRED | 如果存在事物的话,就继续这个事物,如果不存在,新建一个事物。 |
PROPAGATION_SUPPORTS | 如果存在事物的话,就继续这个事物,如果不存在,就以非事务的方式进行。 |
PROPAGATION_MANDATORY | 必须在现存事物中执行,否则抛出异常。 |
PROPAGATION_REQUIRES_NEW | 建立一个新事物,如果现存一个事物,则暂停它。 |
PROPAGATION_NOT_SUPPORTED | 不再事务中执行,如果现存事物,则暂停它。 |
PROPAGATION_NEVER | 不再事务中执行,如果现存事物,则抛出异常。 |
PROPAGATION_NESTED | 在一个嵌入的事物中执行,否则同PROPAGATION_REQUIRED |
上述参数是在org.springframework.transaction.TransactionDefinition接口中定义的(类型是public static final,值从0到6)。上述参数中最常用的是PROPAGATION_REQUIRED。
2. 隔离等级(isolation level)
在一个应用应用程序中,可能有多个事务在运行,这时就会产生一些问题。
dirty read
一个事物更新了数据库中的某些数据,另一个事物读取了这些数据,这时前一个事物由于某些原因回滚了,那么第二个事物读取的数据就是“脏数据”。
non-repeatable read
一个事物需要两次查询同一数据,但两次查询中间可能有另外一个事物更改了这个数据,导致前一个事物两次读出的数据不一致。
phantom read
一个事物两次查询同一个表,但两次查询中间可能有另外一个事物又向这个表中插入了一些新数据,导致前一个事物的两次查询不一致。
为了解决以上问题,Spring的事物管理定义了一些隔离级别,所谓“隔离”,即对数据的锁定。
参数 | 含义 |
ISOLATION_DEFAULT | 使用数据库默认的隔离级别 |
ISOLATION_READ_UNCOMMITTED | 容许事物读取其他并行事物还未提交的数据。这种级别会出现上面三种情况。 |
ISOLATION_READ_COMMITTED | 容许事物读取其他并行事物已经提交(commit)的数据,可防止dirty read |
ISOLATION_REPEATABLE_READ | 这种级别会可以防止上面三种情况发生。 |
ISOLATION_SERIALIZABLE | 使用事物锁,锁定相应数据,可以防止上面三种情况发生,但效率比较低。 |
上述参数也是在org.springframework.transaction.TransactionDefinition接口中定义的(类型是public static final,值为-1,1,2,4,8)。上述参数中最常用的是ISOLATION_DEFAULT。
3. read only
应用这项属性时,底层的数据库可以对读取进行最优化,但要配合PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW或PROPAGATION_NESTED使用,即只能在事物中使用。
4. timeout
在多事物并行情况下,为了保证正确性,有些事物的操作会有延迟,甚至死锁。设置事物超时时间,可以避免事物的长时间等待。设置事物超时时间也要配合PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW或PROPAGATION_NESTED使用。
以上的四种属性及其相应方法都定义在org.springframework.transaction.TransactionDefinition接口及其实现类(如org.springframework.transaction.support.DefaultTransactionDefinition)里。
标签:
原文地址:http://my.oschina.net/sniperLi/blog/397356