`

Spring事务传播机制 收集及学习笔记

 
阅读更多

###事务是允许你将多个操作组合成要么全部发生,要么全部不发生的工作单元,这些单元的特征是使用同一个connection,并且这些操作同时提交,同时回滚。

两个操作看是否在同一个事务中关键是看这两个操作十分使用同一个connection,接下来要考虑的就是让这个两个操作同时提交,所以需要将 autocommit set 为false。这样两个操作便是在同一个 事务了。

 

##1.事务最终还是要靠底层database的connection来实现的.

    2.使用一个事务的目标是让几个操作要么一起提交,要么一起回滚.

   3.要达到这个目标,本质上要让几个操作或Dao使用的是同一个data source,也就是同一个connection.

   所以一个事务要控制多个操作,实际就是要让这些操作尽量使用同一个connection。

   4.一个Hibernate session其实就是基于一个database connection 的,所以保证了多个操作在同一个Hibernate session就是保证了同一个database connection. 可以说Hibernate session和database connection是等同的.

   5.在ssh, spring事务管理主要是通过对Hibernate session 进行控制管理,也就是说在多个Hibernate dao进行操作时,为了让他们在同一个事务下,那么就要保证他们使用同一个session。

个人觉得spring事务传播机制的使用主要考虑当前运行的方法是否需要使用当前的事务,也就是外部事务。如果需要使用外部事务,那么方法的内部事务和外部事务是什么样的关系,是否是同一个事务还是一个新的事务,如果是新的事务,它是怎么样和外面事务进行工作的。 

http://kingj.iteye.com/blog/1461600

由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于:PROPAGATION_REQUIRES_NEW 将创建一个全新的事务,它和外层事务没有任何关系,而 PROPAGATION_NESTED 将创建一个依赖于外层事务的子事务,当外层事务提交或回滚时,子事务也会连带提交和回滚。

###1)转自http://nicholasbugs.iteye.com/blog/226901

Spring事务传播机制

PROPAGATION_REQUIRES_NEW starts a new, independent "inner" transaction for the given scope. This transaction will be committed or rolled back completely independent from the outer transaction, having its own isolation scope, its own set of locks, etc. The outer transaction will get suspended at the beginning of the inner one, and resumed once the inner one has completed.

PROPAGATION_REQUIRES_NEW会在当前运行的范围内创建一个全新的内部事务,这个的事务会独立地被提交或回滚(完全独立于外部事务),它拥有自己的隔离级别,以及锁等等。当内部事务被执行时,外部事务会被挂起,知道内部事务结束时才会继续执行。

Such independent inner transactions are for example used for id generation through manual sequences, where the access to the sequence table should happen in its own transactions, to keep the lock there as short as possible. The goal there is to avoid tying the sequence locks to the (potentially much longer running) outer transaction, with the sequence lock not getting released before completion of the outer transaction.
这种独立的内部事务会被诸如从序列生成ID的应用中,从序列取得id的动作应该发生在自己的事务内部,并且保持对这个sequence表的锁的时间越短越好。这么做是为了避免在获得ID以后可能仍然在很长时间内持有这个sequence表的锁(外部事务仍在运行中)。

PROPAGATION_NESTED on the other hand starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. íf the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction.
PROPAGATION_NESTED启动了一次嵌套的事务(一个当前事务的子事务),在内部嵌套事务开始时,会保留一个保存点(savepoint),如果内部嵌套事务失败,将会回滚到savepoint处,内部嵌套事务是外部事务的一部分,所以只有在外部事务完成时才会被提交。

Nested transactions essentially allow to try some execution subpaths as subtransactions: rolling back to the state at the beginning of the failed subpath, continuing with another subpath or with the main execution path there - all within one isolated transaction, and not losing any previous work done within the outer transaction.
嵌套事务可以满足子事务“多路执行”的需求:回滚到失败的内部嵌套事务开始的地方,然后执行另外的一个内部嵌套事务,或者继续执行主事务-上面提及的事务都是独立的,不会丢失外部事务所作的修改。

For example, consider parsing a very large input file consisting of account transfer blocks: The entire file should essentially be parsed within one transaction, with one single commit at the end. But if a block fails, its transfers need to be rolled back, writing a failure marker somewhere. You could either start over the entire transaction every time a block fails, remembering which blocks to skip - or you mark each block as a nested transaction, only rolling back that specific set of operations, keeping the previous work of the outer transaction. The latter is of course much more efficient, in particular when a block at the end of the file fails.

例如,分块传输一个很大的文件,整个文件的传输应该放在一个事务内部,在文件传输完成后提交事务。如果一个文件块传输失败了,就需要在某个地方写一个失败标记,然后重新传这个文件块,你可以在每次传输一个文件块失败时重新开始事务,然后记住那些块已经成功传输了,忽略即可-或者你可以把每个文件块的传输作为一个内部嵌套事务,只回滚失败的事务,保存前面事务的更改结果,当然这种方法要有效得多,想像一个最后一个文件块出错的情形。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics