
Sping的事务 和 数据库的事务是不同的概念,数据库的事务一般称为底层事务
Spring的事务是对这种事务的抽象 我称之为逻辑事务
Spring对事务的功能进行了扩展,除了基本的Isolation之外,增加了PROPAGATION传播特性,Timeout属性,readOnly属性 ,回滚条件
Isolation是作用于物理属性的
PROPAGATION传播特性 是通过spring自己的事务管理实现的事务嵌套的处理逻辑
Timeout属性,readOnly属性 则都是作用于Connection上的
下面我把Spring中的事务的5中属性归纳如下
在spring中 事务有5个属性
- 传播特性
- 隔离级别
- 回滚规则
- 事务超时
- 是否只读
除了回滚规则外 其他的属性都定义在TransactionDefinition的实现类里面
一般来讲 就是DefaultTransactionDefinition了
回滚规则的判断体现在接口TransactionAttribute里面 实现则是在RuleBasedTransactionAttribute里面
1.传播特性PROPAGATION:
新的事务应该被启动还是挂起?方法是否要在事务的环境中运行?
- PROPAGATION_MANDATORY 方法必须在事务中运行,如果没有事务就要抛出错误 MANDATORY 是强制的意思
- PROPAGATION_NESTED 嵌套,外层有事务的情况下 如果内层要打开事务就打开事务嵌套运行,如果内层没有事务就加入到上层事务中去,嵌套事务是可以独立提交和回滚的 (对于jdbc Spring其实在内层没有开启新事务,只是在内层方法前设置了savepoint)
- PROPAGATION_NEVER 表示这个方法不能运行在事务中,如果上下文有事务 就要抛出异常
- PROPAGATION_NOT_SUPPORTED 表示当前方法运行的时候 如果有上下文事务,那么上下文事务会被挂起 等该方法执行结束,上下文事务恢复
- PROPAGATION_REQUIRED 表示当前方法必须运行在事务中,如果上下文有事务就加入上下文事务;上下文没有事务,就启动一个新事务
- PROPAGATION_REQUIRES_NEW 当前方法一定会启动自己的事务,如果有上下文事务,上下文事务会被挂起的 (对于jdbc Spring在内层开启新事务(创建了新的Connection 内层事务是独立的开启 提交 回滚的)
- PROPAGATION_SUPPORTS 表示当前方法不需要上下文事务,但是如果有上下文事务的话 还是可以在上下文事务里运行的
2.隔离级别ISOLATION
一个事务,可能受其他并发事务的影响程度
3个问题:
脏读: 事务A在执行过程中 读取到了事务B修改过但是尚未提交的数据
不可重复读: 事务A读取了两次,两次结果不同, 原因是中途事务B修改了数据并且提交了
幻读: 事务A读取了3行数据 过了一会再读取读出来4条数据, 原因是事务B中途insert了一条数据; 多出来的这一条数据叫做幻影数据
- ISOLATION_DEFAULT 数据库默认隔离级别 mysql的话 就是read_committed
- ISOLATION_READ_UNCOMMITTED 读未提交 会导致脏读, 但是也是效率最高的一种级别
- IOSLATION_READ_COMMITTED 读已提交,最常用的的级别,可以防止脏读
- ISOLATION_REPEATABLE_READ 可重复读, 能防止脏读和重复读, 但是防不了幻读
- ISOLATION_SERIALIZABLE *别,可防幻读
3.只读 readOnly
private boolean readOnly = false; public final void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
} public final boolean isReadOnly() {
return this.readOnly;
}
4.事务超时 timeOut
private int timeout = TIMEOUT_DEFAULT; public final void setTimeout(int timeout) {
if (timeout < TIMEOUT_DEFAULT) {
throw new IllegalArgumentException("Timeout must be a positive integer or TIMEOUT_DEFAULT");
}
this.timeout = timeout;
} public final int getTimeout() {
return this.timeout;
}
5.回滚规则
private List<RollbackRuleAttribute> rollbackRules; public void setRollbackRules(List<RollbackRuleAttribute> rollbackRules) {
this.rollbackRules = rollbackRules;
}
public List<RollbackRuleAttribute> getRollbackRules() {
if (this.rollbackRules == null) {
this.rollbackRules = new LinkedList<RollbackRuleAttribute>();
}
return this.rollbackRules;
} //判断当前抛出的异常是否要回滚
public boolean rollbackOn(Throwable ex) { RollbackRuleAttribute winner = null;
int deepest = Integer.MAX_VALUE; if (this.rollbackRules != null) {
for (RollbackRuleAttribute rule : this.rollbackRules) {
int depth = rule.getDepth(ex);
if (depth >= 0 && depth < deepest) {
deepest = depth;
winner = rule;
}
}
} if (logger.isTraceEnabled()) {
logger.trace("Winning rollback rule is: " + winner);
} // User superclass behavior (rollback on unchecked) if no rule matches.
if (winner == null) {
logger.trace("No relevant rollback rule found: applying default rules");
return super.rollbackOn(ex);
} return !(winner instanceof NoRollbackRuleAttribute); //判断winner是否是不回滚的异常类型
}