spring事务作用于当前线程,不能跨线程共享。
隔离级别isolation
隔离级别是指一个事务访问其他事务操作的资源的一种控制手段。
- default:与数据库的事务级别保持一致 。
- read_committed: 避免胀读,可能发生不可重复读和幻影读。
- read_uncommited: 胀读、不可重复读,幻影读都可能发生。
- reapeatable_read: 避免胀读和不可重复读,幻影读可能发生。
- serializable: 避免胀读、不可重复读,幻影读。
* 胀读:一个事务读到了其他事务未提交的更改的数据,这里的更改包括:insert,update, delete。
* 不可重复读:在一个事务中,首先执行select获取一条数据,此时另外一个事务修改了该条数据,并commit,第一个事务再次select这条数据,和第一次select的内容不同。
* 幻影读:幻影读是不可重复读的一种特例,在一个事务中,首先执行select获取一批数据,此时另外一个事务插入了新数据,并commit,第一个事务再次select数据,和第一次获取的内容不同。
传播机制Propagation
事务的传播机制解决的是多个事务之前的包含、传递,嵌套等关系。
- mandatory: 当前方法必须运行于一个事务中,如果不存在事务,则抛出异常。
- nested:如果当前还没线程,就创建一个新线程;如果已存在一个线程,则启动一个subtransaction,实质就是设置一个safepoint,如果当前方法出现异常,则回滚到safepoint。
- never:工作在非事务环境下,如有有事务则抛出异常。
- not_supported: 工作在非事务环境下,如果存在事务,则挂起事务。何为挂起事务,参见:https://stackoverflow.com/questions/33729810/what-does-suspending-a-transaction-means。事务挂起其实就是被挂起的事务再次唤醒后,如果rollback,对挂起期间提交的事务不会产生影响。
- required:当前方法必须要启动一个事务,如果事务已存在,则加入到事务中,如果不存在则新建一个新事务。
- requires_new:新建一个事务,如果已存在一个事务,则挂起这个已存在的事务。
- supports: 如果有事务,进入改事务执行;如果不存在事务,则已非事务方式执行。
Spring共提供了7种传播机制,但日常工作中未必都用到过,为加深理解,方便记忆,我们可以从对已有事务的依赖和是否新建事务、针对已有事务的反应等几个个方面进行比较。
传播类型 | 是否需要已有事务 | 是否新建事务(Y/C/N) | 是否允许存在已有事务 |
---|---|---|---|
mandatory | Y | N | Y |
nested | N | C | Y |
required | N | C | Y |
required_new | N | Y | Y |
supports | N | N | Y |
never | N | N | N(抛异常) |
not_supported | N | N | Y |